@@ -100,6 +100,79 @@ defmodule Mix.Tasks.DepsTest do
100100 end )
101101 end
102102
103+ test "filters dependencies by name" do
104+ in_fixture ( "deps_status" , fn ->
105+ Mix.Project . push ( DepsApp )
106+
107+ Mix.Tasks.Deps . run ( [ "ok" ] )
108+
109+ assert_received { :mix_shell , :info , [ "* ok (https://github.com/elixir-lang/ok.git) (mix)" ] }
110+ refute_received { :mix_shell , :info , [ "* invalidvsn" <> _ ] }
111+ refute_received { :mix_shell , :info , [ "* invalidapp" <> _ ] }
112+ refute_received { :mix_shell , :info , [ "* noappfile" <> _ ] }
113+ refute_received { :mix_shell , :info , [ "* nosemver" <> _ ] }
114+ end )
115+ end
116+
117+ test "warns when filtering for unknown dependencies" do
118+ in_fixture ( "deps_status" , fn ->
119+ Mix.Project . push ( DepsApp )
120+
121+ Mix.Tasks.Deps . run ( [ "ok" , "unknowndep" ] )
122+
123+ assert_received { :mix_shell , :info , [ "* ok (https://github.com/elixir-lang/ok.git) (mix)" ] }
124+ assert_received { :mix_shell , :error , [ "warning: unknown dependency unknowndep" ] }
125+ end )
126+ end
127+
128+ test "filters dependencies preserving argument order" do
129+ in_fixture ( "deps_status" , fn ->
130+ Mix.Project . push ( DepsApp )
131+
132+ Mix.Tasks.Deps . run ( [ "nosemver" , "unknowndep2" , "ok" , "unknowndep1" , "invalidapp" ] )
133+
134+ assert_output_order ( [
135+ { :info , "nosemver" } ,
136+ { :info , "ok" } ,
137+ { :info , "invalidapp" } ,
138+ { :error , "unknowndep2" } ,
139+ { :error , "unknowndep1" }
140+ ] )
141+ end )
142+ end
143+
144+ test "deduplicates arguments preserving first occurrence order" do
145+ in_fixture ( "deps_status" , fn ->
146+ Mix.Project . push ( DepsApp )
147+
148+ Mix.Tasks.Deps . run ( [ "ok" , "ok" , "nosemver" , "unknowndep" , "ok" , "unknowndep" ] )
149+
150+ messages = receive_shell_messages ( )
151+
152+ assert_output_once ( messages , "ok" )
153+ assert_output_once ( messages , "nosemver" )
154+ assert_output_once ( messages , "unknowndep" )
155+
156+ assert_output_order ( messages , [ { :info , "ok" } , { :info , "nosemver" } , { :error , "unknowndep" } ] )
157+ end )
158+ end
159+
160+ test "lists all dependencies in alphabetical order when no filter is given" do
161+ in_fixture ( "deps_status" , fn ->
162+ Mix.Project . push ( DepsApp )
163+
164+ Mix.Tasks.Deps . run ( [ ] )
165+
166+ assert_output_order ( [
167+ { :info , "invalidapp" } ,
168+ { :info , "invalidvsn" } ,
169+ { :info , "noappfile" } ,
170+ { :info , "nosemver" } ,
171+ { :info , "ok" }
172+ ] )
173+ end )
174+ end
175+
103176 test "prints list of dependencies and their status, including req mismatches and custom apps" do
104177 in_fixture ( "deps_status" , fn ->
105178 Mix.Project . push ( ReqDepsApp )
@@ -977,4 +1050,75 @@ defmodule Mix.Tasks.DepsTest do
9771050 assert File . exists? ( "deps/ok" )
9781051 end )
9791052 end
1053+
1054+ ## Helpers
1055+
1056+ defp assert_output_once ( messages , dep ) do
1057+ matches = Enum . count ( messages , & ( info_message? ( & 1 , dep ) or warning_message? ( & 1 , dep ) ) )
1058+
1059+ if matches != 1 do
1060+ flunk ( """
1061+ Expected output for #{ dep } to appear only once!
1062+
1063+ Output:
1064+ #{ inspect ( messages ) }
1065+ """ )
1066+ end
1067+ end
1068+
1069+ defp assert_output_order ( expected ) do
1070+ assert_output_order ( receive_shell_messages ( ) , expected )
1071+ end
1072+
1073+ defp assert_output_order ( output , expected ) do
1074+ # Find the index of each expected output line
1075+ indices =
1076+ Enum . map ( expected , fn
1077+ { :info , dep } -> Enum . find_index ( output , & info_message? ( & 1 , dep ) )
1078+ { :error , dep } -> Enum . find_index ( output , & warning_message? ( & 1 , dep ) )
1079+ end )
1080+
1081+ if not Enum . all? ( indices ) do
1082+ flunk ( """
1083+ Expected output not found!
1084+
1085+ Expected:
1086+ #{ inspect ( expected ) }
1087+
1088+ Output:
1089+ #{ inspect ( output ) }
1090+ """ )
1091+ end
1092+
1093+ if not strictly_increasing? ( indices ) do
1094+ flunk ( """
1095+ Output not in expected order!
1096+
1097+ Expected:
1098+ #{ inspect ( expected ) }
1099+
1100+ Output:
1101+ #{ inspect ( output ) }
1102+ """ )
1103+ end
1104+ end
1105+
1106+ defp receive_shell_messages ( acc \\ [ ] ) do
1107+ receive do
1108+ { :mix_shell , level , [ line ] } when level in [ :info , :error ] ->
1109+ receive_shell_messages ( [ { level , line } | acc ] )
1110+ after
1111+ 0 -> Enum . reverse ( acc )
1112+ end
1113+ end
1114+
1115+ defp info_message? ( { :info , line } , dep ) , do: line =~ ~r/ ^\* #{ dep } /
1116+ defp info_message? ( _message , _dep ) , do: false
1117+
1118+ defp warning_message? ( { :error , line } , dep ) , do: line =~ ~r/ ^warning: .* #{ dep } /
1119+ defp warning_message? ( _message , _dep ) , do: false
1120+
1121+ defp strictly_increasing? ( [ ] ) , do: true
1122+ defp strictly_increasing? ( [ _ ] ) , do: true
1123+ defp strictly_increasing? ( [ a , b | rest ] ) , do: a < b and strictly_increasing? ( [ b | rest ] )
9801124end
0 commit comments