@@ -23,17 +23,23 @@ public void SetupMocksAndUriHandler()
2323 _mUserNotifier = new Mock < IUserNotifier > ( MockBehavior . Strict ) ;
2424 _mRdpConnector = new Mock < IRdpConnector > ( MockBehavior . Strict ) ;
2525 _mRpcController = new Mock < IRpcController > ( MockBehavior . Strict ) ;
26+ _mCredentialManager = new Mock < ICredentialManager > ( MockBehavior . Strict ) ;
2627
27- uriHandler = new UriHandler ( logger , _mRpcController . Object , _mUserNotifier . Object , _mRdpConnector . Object ) ;
28+ uriHandler = new UriHandler ( logger ,
29+ _mRpcController . Object ,
30+ _mUserNotifier . Object ,
31+ _mRdpConnector . Object ,
32+ _mCredentialManager . Object ) ;
2833 }
2934
3035 private Mock < IUserNotifier > _mUserNotifier ;
3136 private Mock < IRdpConnector > _mRdpConnector ;
3237 private Mock < IRpcController > _mRpcController ;
38+ private Mock < ICredentialManager > _mCredentialManager ;
3339 private UriHandler uriHandler ; // Unit under test.
3440
3541 [ SetUp ]
36- public void AgentAndWorkspaceFixtures ( )
42+ public void AgentWorkspaceAndCredentialFixtures ( )
3743 {
3844 agent11 = new Agent ( ) ;
3945 agent11 . Fqdn . Add ( "workspace1.coder" ) ;
@@ -54,94 +60,116 @@ public void AgentAndWorkspaceFixtures()
5460 Workspaces = [ workspace1 ] ,
5561 Agents = [ agent11 ] ,
5662 } ;
63+
64+ credentialModel1 = new CredentialModel
65+ {
66+ State = CredentialState . Valid ,
67+ CoderUrl = new Uri ( "https://coder.test" ) ,
68+ } ;
5769 }
5870
5971 private Agent agent11 ;
6072 private Workspace workspace1 ;
6173 private RpcModel modelWithWorkspace1 ;
74+ private CredentialModel credentialModel1 ;
6275
6376 [ Test ( Description = "Open RDP with username & password" ) ]
6477 [ CancelAfter ( 30_000 ) ]
6578 public async Task Mainline ( CancellationToken ct )
6679 {
67- var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/agent11/rdp?username=testy&password=sesame" ) ;
80+ var input = new Uri (
81+ "coder://coder.test/v0/open/ws/workspace1/agent/agent11/rdp?username=testy&password=sesame" ) ;
6882
83+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
6984 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
7085 var expectedCred = new RdpCredentials ( "testy" , "sesame" ) ;
7186 _ = _mRdpConnector . Setup ( m => m . WriteCredentials ( agent11 . Fqdn [ 0 ] , expectedCred ) ) ;
7287 _ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
7388 . Returns ( Task . CompletedTask ) ;
7489 await uriHandler . HandleUri ( input , ct ) ;
90+ _mRdpConnector . Verify ( m => m . WriteCredentials ( It . IsAny < string > ( ) , It . IsAny < RdpCredentials > ( ) ) ) ;
91+ _mRdpConnector . Verify ( m => m . Connect ( It . IsAny < string > ( ) , It . IsAny < int > ( ) , ct ) , Times . Once ) ;
7592 }
7693
7794 [ Test ( Description = "Open RDP with no credentials" ) ]
7895 [ CancelAfter ( 30_000 ) ]
7996 public async Task NoCredentials ( CancellationToken ct )
8097 {
81- var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/agent11/rdp" ) ;
98+ var input = new Uri ( "coder://coder.test/ v0/open/ws/workspace1/agent/agent11/rdp" ) ;
8299
100+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
83101 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
84102 _ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
85103 . Returns ( Task . CompletedTask ) ;
86104 await uriHandler . HandleUri ( input , ct ) ;
105+ _mRdpConnector . Verify ( m => m . Connect ( It . IsAny < string > ( ) , It . IsAny < int > ( ) , ct ) , Times . Once ) ;
87106 }
88107
89108 [ Test ( Description = "Unknown app slug" ) ]
90109 [ CancelAfter ( 30_000 ) ]
91110 public async Task UnknownApp ( CancellationToken ct )
92111 {
93- var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/agent11/someapp" ) ;
112+ var input = new Uri ( "coder://coder.test/ v0/open/ws/workspace1/agent/agent11/someapp" ) ;
94113
114+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
95115 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
96116 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "someapp" ) , ct ) )
97117 . Returns ( Task . CompletedTask ) ;
98118 await uriHandler . HandleUri ( input , ct ) ;
119+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
99120 }
100121
101122 [ Test ( Description = "Unknown agent name" ) ]
102123 [ CancelAfter ( 30_000 ) ]
103124 public async Task UnknownAgent ( CancellationToken ct )
104125 {
105- var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/wrongagent/rdp" ) ;
126+ var input = new Uri ( "coder://coder.test/ v0/open/ws/workspace1/agent/wrongagent/rdp" ) ;
106127
128+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
107129 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
108130 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "wrongagent" ) , ct ) )
109131 . Returns ( Task . CompletedTask ) ;
110132 await uriHandler . HandleUri ( input , ct ) ;
133+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
111134 }
112135
113136 [ Test ( Description = "Unknown workspace name" ) ]
114137 [ CancelAfter ( 30_000 ) ]
115138 public async Task UnknownWorkspace ( CancellationToken ct )
116139 {
117- var input = new Uri ( "coder:/v0/open/ws/wrongworkspace/agent/agent11/rdp" ) ;
140+ var input = new Uri ( "coder://coder.test/ v0/open/ws/wrongworkspace/agent/agent11/rdp" ) ;
118141
142+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
119143 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
120144 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "wrongworkspace" ) , ct ) )
121145 . Returns ( Task . CompletedTask ) ;
122146 await uriHandler . HandleUri ( input , ct ) ;
147+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
123148 }
124149
125150 [ Test ( Description = "Malformed Query String" ) ]
126151 [ CancelAfter ( 30_000 ) ]
127152 public async Task MalformedQuery ( CancellationToken ct )
128153 {
129154 // there might be some query string that gets the parser to throw an exception, but I could not find one.
130- var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/agent11/rdp?%&##" ) ;
155+ var input = new Uri ( "coder://coder.test/ v0/open/ws/workspace1/agent/agent11/rdp?%&##" ) ;
131156
157+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
132158 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
133159 // treated the same as if we just didn't include credentials
134160 _ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
135161 . Returns ( Task . CompletedTask ) ;
136162 await uriHandler . HandleUri ( input , ct ) ;
163+ _mRdpConnector . Verify ( m => m . Connect ( It . IsAny < string > ( ) , It . IsAny < int > ( ) , ct ) , Times . Once ) ;
137164 }
138165
139166 [ Test ( Description = "VPN not started" ) ]
140167 [ CancelAfter ( 30_000 ) ]
141168 public async Task VPNNotStarted ( CancellationToken ct )
142169 {
143- var input = new Uri ( "coder:/v0/open/ws/wrongworkspace/agent/agent11/rdp" ) ;
170+ var input = new Uri ( "coder://coder.test/ v0/open/ws/wrongworkspace/agent/agent11/rdp" ) ;
144171
172+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
145173 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( new RpcModel
146174 {
147175 VpnLifecycle = VpnLifecycle . Starting ,
@@ -150,29 +178,79 @@ public async Task VPNNotStarted(CancellationToken ct)
150178 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "Coder Connect" ) , ct ) )
151179 . Returns ( Task . CompletedTask ) ;
152180 await uriHandler . HandleUri ( input , ct ) ;
181+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
153182 }
154183
155184 [ Test ( Description = "Wrong number of components" ) ]
156185 [ CancelAfter ( 30_000 ) ]
157186 public async Task UnknownNumComponents ( CancellationToken ct )
158187 {
159- var input = new Uri ( "coder:/v0/open/ws/wrongworkspace/agent11/rdp" ) ;
188+ var input = new Uri ( "coder://coder.test/ v0/open/ws/wrongworkspace/agent11/rdp" ) ;
160189
190+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
161191 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
162192 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) )
163193 . Returns ( Task . CompletedTask ) ;
164194 await uriHandler . HandleUri ( input , ct ) ;
195+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
165196 }
166197
167198 [ Test ( Description = "Unknown prefix" ) ]
168199 [ CancelAfter ( 30_000 ) ]
169200 public async Task UnknownPrefix ( CancellationToken ct )
170201 {
171- var input = new Uri ( "coder:/v300/open/ws/workspace1/agent/agent11/rdp" ) ;
202+ var input = new Uri ( "coder://coder.test/ v300/open/ws/workspace1/agent/agent11/rdp" ) ;
172203
204+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
173205 _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
174206 _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) )
175207 . Returns ( Task . CompletedTask ) ;
176208 await uriHandler . HandleUri ( input , ct ) ;
209+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
210+ }
211+
212+ [ Test ( Description = "Unknown authority" ) ]
213+ [ CancelAfter ( 30_000 ) ]
214+ public async Task UnknownAuthority ( CancellationToken ct )
215+ {
216+ var input = new Uri ( "coder://unknown.test/v0/open/ws/workspace1/agent/agent11/rdp" ) ;
217+
218+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
219+ _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
220+ _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( @"unknown\.test" ) , ct ) )
221+ . Returns ( Task . CompletedTask ) ;
222+ await uriHandler . HandleUri ( input , ct ) ;
223+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
224+ }
225+
226+ [ Test ( Description = "Missing authority" ) ]
227+ [ CancelAfter ( 30_000 ) ]
228+ public async Task MissingAuthority ( CancellationToken ct )
229+ {
230+ var input = new Uri ( "coder:/v0/open/ws/workspace1/agent/agent11/rdp" ) ;
231+
232+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
233+ _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
234+ _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "Coder server" ) , ct ) )
235+ . Returns ( Task . CompletedTask ) ;
236+ await uriHandler . HandleUri ( input , ct ) ;
237+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
238+ }
239+
240+ [ Test ( Description = "Not signed in" ) ]
241+ [ CancelAfter ( 30_000 ) ]
242+ public async Task NotSignedIn ( CancellationToken ct )
243+ {
244+ var input = new Uri ( "coder://coder.test/v0/open/ws/workspace1/agent/agent11/rdp" ) ;
245+
246+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( new CredentialModel ( )
247+ {
248+ State = CredentialState . Invalid ,
249+ } ) ;
250+ _mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
251+ _mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "signed in" ) , ct ) )
252+ . Returns ( Task . CompletedTask ) ;
253+ await uriHandler . HandleUri ( input , ct ) ;
254+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
177255 }
178256}
0 commit comments