@@ -484,6 +484,65 @@ describe('runCreate', () => {
484484 expect ( result . type ) . toBe ( 'backend' ) ;
485485 } ) ;
486486
487+ it ( 'P6 — rejects a blank inline --password before POSTing' , async ( ) => {
488+ const { credentialsPath } = makeCreds ( ) ;
489+ const fetchImpl = vi . fn ( async ( ) => {
490+ throw new Error ( 'should not hit network — validation must fire client-side' ) ;
491+ } ) ;
492+
493+ await expect (
494+ runCreate (
495+ {
496+ profile : 'default' ,
497+ output : 'json' ,
498+ debug : false ,
499+ type : 'backend' ,
500+ name : 'Auth Project' ,
501+ password : ' ' ,
502+ } ,
503+ {
504+ credentialsPath,
505+ fetchImpl : fetchImpl as unknown as typeof fetch ,
506+ stdout : ( ) => { } ,
507+ stderr : ( ) => { } ,
508+ } ,
509+ ) ,
510+ ) . rejects . toMatchObject ( { code : 'VALIDATION_ERROR' , exitCode : 5 } ) ;
511+ expect ( fetchImpl ) . not . toHaveBeenCalled ( ) ;
512+ } ) ;
513+
514+ it ( 'P6 — preserves surrounding spaces in a non-empty inline --password' , async ( ) => {
515+ const { credentialsPath } = makeCreds ( ) ;
516+ const sentBodies : unknown [ ] = [ ] ;
517+ const createdProject : CliProject = {
518+ ...PROJECT_FIXTURE ,
519+ id : 'proj_password_spaces' ,
520+ type : 'backend' ,
521+ name : 'Password Spaces' ,
522+ } ;
523+ const fetchImpl = ( async ( _input : Parameters < typeof fetch > [ 0 ] , init : RequestInit = { } ) => {
524+ if ( init . body ) sentBodies . push ( JSON . parse ( init . body as string ) as unknown ) ;
525+ return new Response ( JSON . stringify ( createdProject ) , {
526+ status : 200 ,
527+ headers : { 'content-type' : 'application/json' } ,
528+ } ) ;
529+ } ) as typeof fetch ;
530+
531+ await runCreate (
532+ {
533+ profile : 'default' ,
534+ output : 'json' ,
535+ debug : false ,
536+ type : 'backend' ,
537+ name : 'Password Spaces' ,
538+ password : ' keep spaces ' ,
539+ } ,
540+ { credentialsPath, fetchImpl, stdout : ( ) => { } , stderr : ( ) => { } } ,
541+ ) ;
542+
543+ expect ( ( sentBodies [ 0 ] as Record < string , unknown > ) . password ) . toBe ( ' keep spaces ' ) ;
544+ } ) ;
545+
487546 it ( 'P6 — dry-run returns canned shape without hitting the network' , async ( ) => {
488547 const { credentialsPath } = makeCreds ( ) ;
489548 const fetchImpl = vi . fn ( async ( ) => {
@@ -641,6 +700,32 @@ describe('runUpdate', () => {
641700 expect ( fetchImpl ) . not . toHaveBeenCalled ( ) ;
642701 } ) ;
643702
703+ it ( 'P7 — rejects an empty inline --password before PATCHing' , async ( ) => {
704+ const { credentialsPath } = makeCreds ( ) ;
705+ const fetchImpl = vi . fn ( async ( ) => {
706+ throw new Error ( 'should not hit network — validation must fire client-side' ) ;
707+ } ) ;
708+
709+ await expect (
710+ runUpdate (
711+ {
712+ profile : 'default' ,
713+ output : 'json' ,
714+ debug : false ,
715+ projectId : 'proj_abc' ,
716+ password : '' ,
717+ } ,
718+ {
719+ credentialsPath,
720+ fetchImpl : fetchImpl as unknown as typeof fetch ,
721+ stdout : ( ) => { } ,
722+ stderr : ( ) => { } ,
723+ } ,
724+ ) ,
725+ ) . rejects . toMatchObject ( { code : 'VALIDATION_ERROR' , exitCode : 5 } ) ;
726+ expect ( fetchImpl ) . not . toHaveBeenCalled ( ) ;
727+ } ) ;
728+
644729 it ( 'P7 — dry-run returns canned shape without network call' , async ( ) => {
645730 const { credentialsPath } = makeCreds ( ) ;
646731 const fetchImpl = vi . fn ( async ( ) => {
0 commit comments