@@ -346,10 +346,11 @@ describe.each(testVersions)(
346346 )
347347 } )
348348
349- it ( "supports enum number" , async ( ) => {
349+ it ( "supports closed number enums " , async ( ) => {
350350 const { code, execute} = await getActualFromModel ( {
351351 ...base ,
352352 enum : [ 200 , 301 , 404 ] ,
353+ "x-enum-extensibility" : "closed" ,
353354 } )
354355
355356 expect ( code ) . toMatchInlineSnapshot (
@@ -362,6 +363,26 @@ describe.each(testVersions)(
362363 await expect ( execute ( 404 ) ) . resolves . toBe ( 404 )
363364 } )
364365
366+ it ( "supports open number enums" , async ( ) => {
367+ const { code, execute} = await getActualFromModel ( {
368+ ...base ,
369+ enum : [ 200 , 301 , 404 ] ,
370+ "x-enum-extensibility" : "open" ,
371+ } )
372+
373+ expect ( code ) . toMatchInlineSnapshot ( `
374+ "const x = z.union([
375+ z.literal(200),
376+ z.literal(301),
377+ z.literal(404),
378+ z.unknown().brand("unsupported enum value"),
379+ ])"
380+ ` )
381+
382+ await expect ( execute ( 123 ) ) . resolves . toBe ( 123 )
383+ await expect ( execute ( 404 ) ) . resolves . toBe ( 404 )
384+ } )
385+
365386 it ( "supports minimum" , async ( ) => {
366387 const { code, execute} = await getActualFromModel ( {
367388 ...base ,
@@ -544,6 +565,48 @@ describe.each(testVersions)(
544565 )
545566 } )
546567
568+ it ( "supports closed string enums" , async ( ) => {
569+ const enumValues = [ "red" , "blue" , "green" ]
570+ const { code, execute} = await getActualFromModel ( {
571+ ...base ,
572+ enum : enumValues ,
573+ "x-enum-extensibility" : "closed" ,
574+ } )
575+
576+ expect ( code ) . toMatchInlineSnapshot (
577+ `"const x = z.enum(["red", "blue", "green"])"` ,
578+ )
579+
580+ for ( const value of enumValues ) {
581+ await expect ( execute ( value ) ) . resolves . toBe ( value )
582+ }
583+
584+ await expect ( execute ( "orange" ) ) . rejects . toThrow (
585+ "Invalid enum value. Expected 'red' | 'blue' | 'green', received 'orange'" ,
586+ )
587+ } )
588+
589+ it ( "supports open string enums" , async ( ) => {
590+ const enumValues = [ "red" , "blue" , "green" ]
591+ const { code, execute} = await getActualFromModel ( {
592+ ...base ,
593+ enum : enumValues ,
594+ "x-enum-extensibility" : "open" ,
595+ } )
596+
597+ expect ( code ) . toMatchInlineSnapshot ( `
598+ "const x = z.union([
599+ z.enum(["red", "blue", "green"]),
600+ z.unknown().brand("unsupported enum value"),
601+ ])"
602+ ` )
603+
604+ for ( const value of enumValues ) {
605+ await expect ( execute ( value ) ) . resolves . toBe ( value )
606+ }
607+ await expect ( execute ( "orange" ) ) . resolves . toBe ( "orange" )
608+ } )
609+
547610 it ( "supports nullable string using allOf" , async ( ) => {
548611 const { code, execute} = await getActualFromModel ( {
549612 type : "object" ,
0 commit comments