@@ -594,4 +594,254 @@ public static function provideGetRawTokensTrueTests(): iterable
594
594
yield [['app/console ' , '--no-ansi ' , 'foo:bar ' , 'foo:bar ' ], ['foo:bar ' ]];
595
595
yield [['app/console ' , '--no-ansi ' , 'foo:bar ' , '-- ' , 'argument ' ], ['-- ' , 'argument ' ]];
596
596
}
597
+
598
+ /**
599
+ * @dataProvider unparseProvider
600
+ */
601
+ public function testUnparse (
602
+ ?InputDefinition $ inputDefinition ,
603
+ ArgvInput $ input ,
604
+ ?array $ parsedOptions ,
605
+ array $ expected ,
606
+ )
607
+ {
608
+ if (null !== $ inputDefinition ) {
609
+ $ input ->bind ($ inputDefinition );
610
+ }
611
+
612
+ $ actual = null === $ parsedOptions ? $ input ->unparse () : $ input ->unparse ($ parsedOptions );
613
+
614
+ self ::assertEquals ($ expected , $ actual );
615
+ }
616
+
617
+ public static function unparseProvider (): iterable
618
+ {
619
+ yield 'empty input and empty definition ' => [
620
+ new InputDefinition (),
621
+ new ArgvInput ([]),
622
+ [],
623
+ [],
624
+ ];
625
+
626
+ yield 'empty input and definition with default values: ignore default values ' => [
627
+ new InputDefinition ([
628
+ new InputArgument (
629
+ 'argWithDefaultValue ' ,
630
+ InputArgument::OPTIONAL ,
631
+ 'Argument with a default value ' ,
632
+ 'arg1DefaultValue ' ,
633
+ ),
634
+ new InputOption (
635
+ 'optWithDefaultValue ' ,
636
+ null ,
637
+ InputOption::VALUE_REQUIRED ,
638
+ 'Option with a default value ' ,
639
+ 'opt1DefaultValue ' ,
640
+ ),
641
+ ]),
642
+ new ArgvInput ([]),
643
+ [],
644
+ [],
645
+ ];
646
+
647
+ $ completeInputDefinition = new InputDefinition ([
648
+ new InputArgument (
649
+ 'requiredArgWithoutDefaultValue ' ,
650
+ InputArgument::REQUIRED ,
651
+ 'Argument without a default value ' ,
652
+ ),
653
+ new InputArgument (
654
+ 'optionalArgWithDefaultValue ' ,
655
+ InputArgument::OPTIONAL ,
656
+ 'Argument with a default value ' ,
657
+ 'argDefaultValue ' ,
658
+ ),
659
+ new InputOption (
660
+ 'optWithoutDefaultValue ' ,
661
+ null ,
662
+ InputOption::VALUE_REQUIRED ,
663
+ 'Option without a default value ' ,
664
+ ),
665
+ new InputOption (
666
+ 'optWithDefaultValue ' ,
667
+ null ,
668
+ InputOption::VALUE_REQUIRED ,
669
+ 'Option with a default value ' ,
670
+ 'optDefaultValue ' ,
671
+ ),
672
+ ]);
673
+
674
+ yield 'arguments & options: returns all passed options but ignore default values ' => [
675
+ $ completeInputDefinition ,
676
+ new ArgvInput (['argValue ' , '--optWithoutDefaultValue=optValue ' ]),
677
+ [],
678
+ ['--optWithoutDefaultValue=optValue ' ],
679
+ ];
680
+
681
+ yield 'arguments & options; explicitly pass the default values: the default values are returned ' => [
682
+ $ completeInputDefinition ,
683
+ new ArgvInput (['argValue ' , 'argDefaultValue ' , '--optWithoutDefaultValue=optValue ' , '--optWithDefaultValue=optDefaultValue ' ]),
684
+ [],
685
+ [
686
+ '--optWithoutDefaultValue=optValue ' ,
687
+ '--optWithDefaultValue=optDefaultValue ' ,
688
+ ],
689
+ ];
690
+
691
+ yield 'arguments & options; parsing an argument name instead of an option name: that option is ignored ' => [
692
+ $ completeInputDefinition ,
693
+ new ArgvInput (['argValue ' ]),
694
+ ['requiredArgWithoutDefaultValue ' ],
695
+ [],
696
+ ];
697
+
698
+ yield 'arguments & options; non passed option: it is ignored ' => [
699
+ $ completeInputDefinition ,
700
+ new ArgvInput (['argValue ' ]),
701
+ ['optWithDefaultValue ' ],
702
+ [],
703
+ ];
704
+
705
+ $ createSingleOptionScenario = static fn (
706
+ InputOption $ option ,
707
+ array $ input ,
708
+ array $ expected
709
+ ) => [
710
+ new InputDefinition ([$ option ]),
711
+ new ArgvInput (['appName ' , ...$ input ]),
712
+ [],
713
+ $ expected ,
714
+ ];
715
+
716
+ yield 'option without value ' => $ createSingleOptionScenario (
717
+ new InputOption (
718
+ 'opt ' ,
719
+ null ,
720
+ InputOption::VALUE_NONE ,
721
+ ),
722
+ ['--opt ' ],
723
+ ['--opt ' ],
724
+ );
725
+
726
+ yield 'option without value by shortcut ' => $ createSingleOptionScenario (
727
+ new InputOption (
728
+ 'opt ' ,
729
+ 'o ' ,
730
+ InputOption::VALUE_NONE ,
731
+ ),
732
+ ['-o ' ],
733
+ ['--opt ' ],
734
+ );
735
+
736
+ yield 'option with value required ' => $ createSingleOptionScenario (
737
+ new InputOption (
738
+ 'opt ' ,
739
+ null ,
740
+ InputOption::VALUE_REQUIRED ,
741
+ ),
742
+ ['--opt=foo ' ],
743
+ ['--opt=foo ' ],
744
+ );
745
+
746
+ yield 'option with non string value (bool) ' => $ createSingleOptionScenario (
747
+ new InputOption (
748
+ 'opt ' ,
749
+ null ,
750
+ InputOption::VALUE_REQUIRED ,
751
+ ),
752
+ ['--opt=1 ' ],
753
+ ['--opt=1 ' ],
754
+ );
755
+
756
+ yield 'option with non string value (int) ' => $ createSingleOptionScenario (
757
+ new InputOption (
758
+ 'opt ' ,
759
+ null ,
760
+ InputOption::VALUE_REQUIRED ,
761
+ ),
762
+ ['--opt=20 ' ],
763
+ ['--opt=20 ' ],
764
+ );
765
+
766
+ yield 'option with non string value (float) ' => $ createSingleOptionScenario (
767
+ new InputOption (
768
+ 'opt ' ,
769
+ null ,
770
+ InputOption::VALUE_REQUIRED ,
771
+ ),
772
+ ['--opt=5.3 ' ],
773
+ ['--opt= \'5.3 \'' ],
774
+ );
775
+
776
+ yield 'option with non string value (array of strings) ' => $ createSingleOptionScenario (
777
+ new InputOption (
778
+ 'opt ' ,
779
+ null ,
780
+ InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY ,
781
+ ),
782
+ ['--opt=v1 ' , '--opt=v2 ' , '--opt=v3 ' ],
783
+ ['--opt=v1--opt=v2--opt=v3 ' ],
784
+ );
785
+
786
+ yield 'negatable option (positive) ' => $ createSingleOptionScenario (
787
+ new InputOption (
788
+ 'opt ' ,
789
+ null ,
790
+ InputOption::VALUE_NEGATABLE ,
791
+ ),
792
+ ['--opt ' ],
793
+ ['--opt ' ],
794
+ );
795
+
796
+ yield 'negatable option (negative) ' => $ createSingleOptionScenario (
797
+ new InputOption (
798
+ 'opt ' ,
799
+ null ,
800
+ InputOption::VALUE_NEGATABLE ,
801
+ ),
802
+ ['--no-opt ' ],
803
+ ['--no-opt ' ],
804
+ );
805
+
806
+ $ createEscapeOptionTokenScenario = static fn (
807
+ string $ optionValue ,
808
+ ?string $ expected
809
+ ) => [
810
+ new InputDefinition ([
811
+ new InputOption (
812
+ 'opt ' ,
813
+ null ,
814
+ InputOption::VALUE_REQUIRED ,
815
+ ),
816
+ ]),
817
+ new ArgvInput (['appName ' , '--opt= ' .$ optionValue ]),
818
+ [],
819
+ ['--opt= ' .$ expected ],
820
+ ];
821
+
822
+ yield 'escape token; string token ' => $ createEscapeOptionTokenScenario (
823
+ 'foo ' ,
824
+ 'foo ' ,
825
+ );
826
+
827
+ yield 'escape token; escaped string token ' => $ createEscapeOptionTokenScenario (
828
+ '"foo" ' ,
829
+ escapeshellarg ('"foo" ' ),
830
+ );
831
+
832
+ yield 'escape token; escaped string token with both types of quotes ' => $ createEscapeOptionTokenScenario (
833
+ '"o_id in( \'20 \')" ' ,
834
+ escapeshellarg ('"o_id in( \'20 \')" ' ),
835
+ );
836
+
837
+ yield 'escape token; string token with spaces ' => $ createEscapeOptionTokenScenario (
838
+ 'a b c d ' ,
839
+ escapeshellarg ('a b c d ' ),
840
+ );
841
+
842
+ yield 'escape token; string token with line return ' => $ createEscapeOptionTokenScenario (
843
+ "A \nB'C " ,
844
+ escapeshellarg ("A \nB'C " ),
845
+ );
846
+ }
597
847
}
0 commit comments