@@ -750,3 +750,310 @@ test('(usage) alias :: pre-command :: throws', t => {
750750 t . true ( pid . stderr . toString ( ) . includes ( 'Error: Cannot call `alias()` before defining a command' ) , '~> threw Error w/ message' ) ;
751751 t . end ( ) ;
752752} ) ;
753+
754+
755+ // ---
756+ // Input Order
757+ // ---
758+
759+
760+ test ( '(usage) order :: basic' , t => {
761+ let pid1 = exec ( 'basic.js' , [ '--foo' , 'bar' , 'f' ] ) ;
762+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
763+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
764+ t . is ( pid1 . stdout . toString ( ) , '~> ran "foo" action\n' , '~> command invoked' ) ;
765+
766+ let pid2 = exec ( 'basic.js' , [ '--foo' , 'bar' , 'fo' ] ) ;
767+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
768+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
769+ t . is ( pid2 . stdout . toString ( ) , '~> ran "foo" action\n' , '~> command invoked' ) ;
770+
771+ t . end ( ) ;
772+ } ) ;
773+
774+ test ( '(usage) order :: basic :: error :: invalid command' , t => {
775+ let pid = exec ( 'basic.js' , [ '--foo' , 'bar' , 'fff' ] ) ;
776+ t . is ( pid . status , 1 , 'exits with error code' ) ;
777+ t . is (
778+ pid . stderr . toString ( ) ,
779+ '\n ERROR\n Invalid command: fff\n\n Run `$ bin --help` for more info.\n\n' ,
780+ '~> stderr has "Invalid command: fff" error message'
781+ ) ;
782+ t . is ( pid . stdout . length , 0 , '~> stdout is empty' ) ;
783+ t . end ( ) ;
784+ } ) ;
785+
786+ test ( '(usage) order :: basic :: help' , t => {
787+ let pid1 = exec ( 'basic.js' , [ '--foo' , 'bar' , '-h' ] ) ;
788+ t . is ( pid1 . status , 0 , 'exits with error code' ) ;
789+ t . true ( pid1 . stdout . toString ( ) . includes ( 'Available Commands\n foo' ) , '~> shows global help w/ "Available Commands" text' ) ;
790+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
791+
792+ let pid2 = exec ( 'basic.js' , [ '--foo' , 'bar' , 'f' , '-h' ] ) ;
793+ t . is ( pid2 . status , 0 , 'exits with error code' ) ;
794+ t . true ( pid2 . stdout . toString ( ) . includes ( 'Usage\n $ bin foo [options]' ) , '~> shows command help w/ "Usage" text' ) ;
795+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
796+
797+ t . end ( ) ;
798+ } ) ;
799+
800+
801+ test ( '(usage) order :: args.required' , t => {
802+ let pid = exec ( 'args.js' , [ '--foo' , 'bar' , 'f' , 'value' ] ) ;
803+ t . is ( pid . status , 0 , 'exits without error code' ) ;
804+ t . is ( pid . stdout . toString ( ) , '~> ran "foo" with "value" arg\n' , '~> command invoked' ) ;
805+ t . is ( pid . stderr . length , 0 , '~> stderr is empty' ) ;
806+ t . end ( ) ;
807+ } ) ;
808+
809+ test ( '(usage) order :: args.required :: error :: missing argument' , t => {
810+ let pid = exec ( 'args.js' , [ '--foo' , 'bar' , 'f' ] ) ;
811+ t . is ( pid . status , 1 , 'exits with error code' ) ;
812+ t . is (
813+ pid . stderr . toString ( ) ,
814+ '\n ERROR\n Insufficient arguments!\n\n Run `$ bin foo --help` for more info.\n\n' ,
815+ '~> stderr has "Insufficient arguments!" error message'
816+ ) ;
817+ t . is ( pid . stdout . length , 0 , '~> stdout is empty' ) ;
818+ t . end ( ) ;
819+ } ) ;
820+
821+ test ( '(usage) order :: args.optional' , t => {
822+ let pid = exec ( 'args.js' , [ '--foo' , 'bar' , 'b' ] ) ;
823+ t . is ( pid . status , 0 , 'exits without error code' ) ;
824+ t . is ( pid . stdout . toString ( ) , '~> ran "bar" with "~default~" arg\n' , '~> command invoked' ) ;
825+ t . is ( pid . stderr . length , 0 , '~> stderr is empty' ) ;
826+ t . end ( ) ;
827+ } ) ;
828+
829+ test ( '(usage) order :: args.optional w/ value' , t => {
830+ let pid = exec ( 'args.js' , [ '--foo' , 'bar' , 'b' , 'value' ] ) ;
831+ t . is ( pid . status , 0 , 'exits without error code' ) ;
832+ t . is ( pid . stdout . toString ( ) , '~> ran "bar" with "value" arg\n' , '~> command invoked' ) ;
833+ t . is ( pid . stderr . length , 0 , '~> stderr is empty' ) ;
834+ t . end ( ) ;
835+ } ) ;
836+
837+
838+
839+ test ( '(usage) order :: options.long' , t => {
840+ let pid1 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '--long' ] ) ;
841+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
842+ t . is ( pid1 . stdout . toString ( ) , '~> ran "long" option\n' , '~> command invoked' ) ;
843+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
844+
845+ let pid2 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '-l' ] ) ;
846+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
847+ t . is ( pid2 . stdout . toString ( ) , '~> ran "long" option\n' , '~> command invoked' ) ;
848+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
849+
850+ t . end ( ) ;
851+ } ) ;
852+
853+ test ( '(usage) order :: options.short' , t => {
854+ let pid1 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '--short' ] ) ;
855+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
856+ t . is ( pid1 . stdout . toString ( ) , '~> ran "short" option\n' , '~> command invoked' ) ;
857+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
858+
859+ let pid2 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '-s' ] ) ;
860+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
861+ t . is ( pid2 . stdout . toString ( ) , '~> ran "short" option\n' , '~> command invoked' ) ;
862+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
863+
864+ t . end ( ) ;
865+ } ) ;
866+
867+ test ( '(usage) order :: options.hello' , t => {
868+ let pid1 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '--hello' ] ) ;
869+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
870+ t . is ( pid1 . stdout . toString ( ) , '~> ran "hello" option\n' , '~> command invoked' ) ;
871+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
872+
873+ // shows that '-h' is always reserved
874+ let pid2 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '-h' ] ) ;
875+ let stdout = pid2 . stdout . toString ( ) ;
876+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
877+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
878+
879+ t . not ( stdout , '~> ran "long" option\n' , '~> did NOT run custom "-h" option' ) ;
880+ t . true ( stdout . includes ( '-h, --help Displays this message' ) , '~~> shows `--help` text' ) ;
881+
882+ t . end ( ) ;
883+ } ) ;
884+
885+ test ( '(usage) order :: options.extra' , t => {
886+ let pid = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '--extra=opts' , '--404' ] ) ;
887+ t . is ( pid . status , 0 , 'exits without error code' ) ;
888+ t . is ( pid . stdout . toString ( ) , '~> default with {"404":true,"_":[],"foo":"bar","extra":"opts"}\n' , '~> command invoked' ) ;
889+ t . is ( pid . stderr . length , 0 , '~> stderr is empty' ) ;
890+ t . end ( ) ;
891+ } ) ;
892+
893+ test ( '(usage) order :: options.global' , t => {
894+ let pid1 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '--global' ] ) ;
895+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
896+ t . is ( pid1 . stdout . toString ( ) , '~> default with {"_":[],"foo":"bar","global":true,"g":true}\n' , '~> command invoked' ) ;
897+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
898+
899+ let pid2 = exec ( 'options.js' , [ '--foo' , 'bar' , 'f' , '-g' , 'hello' ] ) ;
900+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
901+ t . is ( pid2 . stdout . toString ( ) , '~> default with {"_":[],"foo":"bar","g":"hello","global":"hello"}\n' , '~> command invoked' ) ;
902+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
903+
904+ t . end ( ) ;
905+ } ) ;
906+
907+ test ( '(usage) order :: options w/o alias' , t => {
908+ let pid1 = exec ( 'options.js' , [ '--foo' , 'bar' , 'b' , 'hello' ] ) ;
909+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
910+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
911+ t . is ( pid1 . stdout . toString ( ) , '~> "bar" with "hello" value\n' , '~> command invoked' ) ;
912+
913+ let pid2 = exec ( 'options.js' , [ '--foo' , 'bar' , 'b' , 'hello' , '--only' ] ) ;
914+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
915+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
916+ t . is ( pid2 . stdout . toString ( ) , '~> (only) "bar" with "hello" value\n' , '~> command invoked' ) ;
917+
918+ let pid3 = exec ( 'options.js' , [ '--foo' , 'bar' , 'b' , 'hello' , '-o' ] ) ;
919+ t . is ( pid3 . status , 0 , 'exits without error code' ) ;
920+ t . is ( pid3 . stderr . length , 0 , '~> stderr is empty' ) ;
921+ t . is ( pid3 . stdout . toString ( ) , '~> "bar" with "hello" value\n' , '~> command invoked' ) ;
922+
923+ t . end ( ) ;
924+ } ) ;
925+
926+
927+ test ( '(usage) order :: unknown.custom' , t => {
928+ let pid1 = exec ( 'unknown2.js' , [ 'f' , '--global' , '--local' ] ) ;
929+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
930+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
931+ t . is ( pid1 . stdout . toString ( ) , '~> ran "foo" with {"_":[],"global":true,"local":true,"g":true,"l":true}\n' , '~> command invoked' ) ;
932+
933+ let pid2 = exec ( 'unknown2.js' , [ '--foo' , 'bar' , 'f' , '--bar' ] ) ;
934+ t . is ( pid2 . status , 1 , 'exits with error code' ) ;
935+ t . is ( pid2 . stdout . length , 0 , '~> stdout is empty' ) ;
936+ t . is (
937+ pid2 . stderr . toString ( ) ,
938+ '\n ERROR\n Custom error: --foo\n\n Run `$ bin --help` for more info.\n\n' , // came first
939+ '~> stderr has "Custom error: --foo" error message' // came first
940+ ) ;
941+
942+ t . end ( ) ;
943+ } ) ;
944+
945+
946+ test ( '(usage) order :: unknown.plain' , t => {
947+ let pid1 = exec ( 'unknown2.js' , [ 'f' , '--flag1' , '--flag2' ] ) ;
948+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
949+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
950+ t . is ( pid1 . stdout . toString ( ) , '~> ran "foo" with {"_":[],"flag1":true,"flag2":true}\n' , '~> command invoked' ) ;
951+
952+ let pid2 = exec ( 'unknown2.js' , [ '--foo' , 'bar' , 'f' , '--flag3' ] ) ;
953+ t . is ( pid2 . status , 1 , 'exits with error code' ) ;
954+ t . is ( pid2 . stdout . length , 0 , '~> stdout is empty' ) ;
955+ t . is (
956+ pid2 . stderr . toString ( ) ,
957+ '\n ERROR\n Custom error: --foo\n\n Run `$ bin --help` for more info.\n\n' , // came first
958+ '~> stderr has "Custom error: --foo" error message' // came first
959+ ) ;
960+
961+ t . end ( ) ;
962+ } ) ;
963+
964+
965+
966+ test ( '(usage) order :: subcommands' , t => {
967+ let pid1 = exec ( 'subs.js' , [ '--foo' , 'bar' , 'r' ] ) ;
968+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
969+ t . is ( pid1 . stdout . toString ( ) , '~> ran "remote" action\n' , '~> ran parent' ) ;
970+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
971+
972+ let pid2 = exec ( 'subs.js' , [ '--foo' , 'bar' , 'rr' , 'origin' , 'foobar' ] ) ;
973+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
974+ t . is ( pid2 . stdout . toString ( ) , '~> ran "remote rename" with "origin" and "foobar" args\n' , '~> ran "rename" child' ) ;
975+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
976+
977+ let pid3 = exec ( 'subs.js' , [ '--foo' , 'bar' , 'ra' , 'origin' , 'foobar' ] ) ;
978+ t . is ( pid3 . status , 0 , 'exits without error code' ) ;
979+ t . is ( pid3 . stdout . toString ( ) , '~> ran "remote add" with "origin" and "foobar" args\n' , '~> ran "add" child' ) ;
980+ t . is ( pid3 . stderr . length , 0 , '~> stderr is empty' ) ;
981+
982+ t . end ( ) ;
983+ } ) ;
984+
985+ test ( '(usage) order :: subcommands :: help' , t => {
986+ let pid1 = exec ( 'subs.js' , [ '--foo' , 'bar' , '--help' ] ) ;
987+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
988+ t . true ( pid1 . stdout . toString ( ) . includes ( 'Available Commands\n remote \n remote add \n remote rename' ) , '~> shows global help w/ "Available Commands" text' ) ;
989+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
990+
991+ let pid2 = exec ( 'subs.js' , [ '--foo' , 'bar' , 'r' , '--help' ] ) ;
992+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
993+ t . true ( pid2 . stdout . toString ( ) . includes ( 'Usage\n $ bin remote [options]' ) , '~> shows "remote" help text' ) ;
994+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
995+
996+ let pid3 = exec ( 'subs.js' , [ '--foo' , 'bar' , 'rr' , '--help' ] ) ;
997+ t . is ( pid3 . status , 0 , 'exits without error code' ) ;
998+ t . true ( pid3 . stdout . toString ( ) . includes ( 'Usage\n $ bin remote rename <old> <new> [options]' ) , '~> shows "remote rename" help text' ) ;
999+ t . is ( pid3 . stderr . length , 0 , '~> stderr is empty' ) ;
1000+
1001+ t . end ( ) ;
1002+ } ) ;
1003+
1004+
1005+ test ( '(usage) order :: default' , t => {
1006+ let pid1 = exec ( 'default.js' , [ '--foo' , 'bar' ] ) ;
1007+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
1008+ t . is ( pid1 . stdout . toString ( ) , '~> ran "foo" action\n' , '~> ran default command' ) ;
1009+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
1010+
1011+ let pid2 = exec ( 'default.js' , [ '--foo' , 'bar' , 'f' ] ) ;
1012+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
1013+ t . is ( pid2 . stdout . toString ( ) , '~> ran "foo" action\n' , '~> ran default command (direct)' ) ;
1014+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
1015+
1016+ let pid3 = exec ( 'default.js' , [ '--foo' , 'bar' , 'b' ] ) ;
1017+ t . is ( pid3 . status , 0 , 'exits without error code' ) ;
1018+ t . is ( pid3 . stdout . toString ( ) , '~> ran "bar" action\n' , '~> ran "bar" command' ) ;
1019+ t . is ( pid3 . stderr . length , 0 , '~> stderr is empty' ) ;
1020+
1021+ t . end ( ) ;
1022+ } ) ;
1023+
1024+ test ( '(usage) order :: default :: help' , t => {
1025+ let pid1 = exec ( 'default.js' , [ '--foo' , 'bar' , '--help' ] ) ;
1026+ t . is ( pid1 . status , 0 , 'exits without error code' ) ;
1027+ t . true ( pid1 . stdout . toString ( ) . includes ( 'Available Commands\n foo \n bar' ) , '~> shows global help w/ "Available Commands" text' ) ;
1028+ t . is ( pid1 . stderr . length , 0 , '~> stderr is empty' ) ;
1029+
1030+ let pid2 = exec ( 'default.js' , [ '--foo' , 'bar' , 'f' , '-h' ] ) ;
1031+ t . is ( pid2 . status , 0 , 'exits without error code' ) ;
1032+ t . true ( pid2 . stdout . toString ( ) . includes ( 'Usage\n $ bin foo [options]' ) , '~> shows command help w/ "Usage" text' ) ;
1033+ t . is ( pid2 . stderr . length , 0 , '~> stderr is empty' ) ;
1034+
1035+ let pid3 = exec ( 'default.js' , [ '--foo' , 'bar' , 'b' , '-h' ] ) ;
1036+ t . is ( pid3 . status , 0 , 'exits without error code' ) ;
1037+ t . true ( pid3 . stdout . toString ( ) . includes ( 'Usage\n $ bin bar [options]' ) , '~> shows command help w/ "Usage" text' ) ;
1038+ t . is ( pid3 . stderr . length , 0 , '~> stderr is empty' ) ;
1039+
1040+ t . end ( ) ;
1041+ } ) ;
1042+
1043+ test ( '(usage) order :: single :: throws' , t => {
1044+ let pid = exec ( 'alias1.js' , [ '--foo' , 'bar' ] ) ;
1045+ t . is ( pid . status , 1 , 'exits with error code' ) ;
1046+ t . is ( pid . stdout . length , 0 , '~> stdout is empty' ) ;
1047+ // throws an error in the process
1048+ t . true ( pid . stderr . toString ( ) . includes ( 'Error: Cannot call `alias()` in "single" mode' ) , '~> threw Error w/ message' ) ;
1049+ t . end ( ) ;
1050+ } ) ;
1051+
1052+ test ( '(usage) order :: pre-command :: throws' , t => {
1053+ let pid = exec ( 'alias2.js' , [ '--foo' , 'bar' ] ) ;
1054+ t . is ( pid . status , 1 , 'exits with error code' ) ;
1055+ t . is ( pid . stdout . length , 0 , '~> stdout is empty' ) ;
1056+ // throws an error in the process
1057+ t . true ( pid . stderr . toString ( ) . includes ( 'Error: Cannot call `alias()` before defining a command' ) , '~> threw Error w/ message' ) ;
1058+ t . end ( ) ;
1059+ } ) ;
0 commit comments