@@ -23,17 +23,23 @@ public void SetupMocksAndUriHandler()
23
23
_mUserNotifier = new Mock < IUserNotifier > ( MockBehavior . Strict ) ;
24
24
_mRdpConnector = new Mock < IRdpConnector > ( MockBehavior . Strict ) ;
25
25
_mRpcController = new Mock < IRpcController > ( MockBehavior . Strict ) ;
26
+ _mCredentialManager = new Mock < ICredentialManager > ( MockBehavior . Strict ) ;
26
27
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 ) ;
28
33
}
29
34
30
35
private Mock < IUserNotifier > _mUserNotifier ;
31
36
private Mock < IRdpConnector > _mRdpConnector ;
32
37
private Mock < IRpcController > _mRpcController ;
38
+ private Mock < ICredentialManager > _mCredentialManager ;
33
39
private UriHandler uriHandler ; // Unit under test.
34
40
35
41
[ SetUp ]
36
- public void AgentAndWorkspaceFixtures ( )
42
+ public void AgentWorkspaceAndCredentialFixtures ( )
37
43
{
38
44
agent11 = new Agent ( ) ;
39
45
agent11 . Fqdn . Add ( "workspace1.coder" ) ;
@@ -54,94 +60,116 @@ public void AgentAndWorkspaceFixtures()
54
60
Workspaces = [ workspace1 ] ,
55
61
Agents = [ agent11 ] ,
56
62
} ;
63
+
64
+ credentialModel1 = new CredentialModel
65
+ {
66
+ State = CredentialState . Valid ,
67
+ CoderUrl = new Uri ( "https://coder.test" ) ,
68
+ } ;
57
69
}
58
70
59
71
private Agent agent11 ;
60
72
private Workspace workspace1 ;
61
73
private RpcModel modelWithWorkspace1 ;
74
+ private CredentialModel credentialModel1 ;
62
75
63
76
[ Test ( Description = "Open RDP with username & password" ) ]
64
77
[ CancelAfter ( 30_000 ) ]
65
78
public async Task Mainline ( CancellationToken ct )
66
79
{
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" ) ;
68
82
83
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
69
84
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
70
85
var expectedCred = new RdpCredentials ( "testy" , "sesame" ) ;
71
86
_ = _mRdpConnector . Setup ( m => m . WriteCredentials ( agent11 . Fqdn [ 0 ] , expectedCred ) ) ;
72
87
_ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
73
88
. Returns ( Task . CompletedTask ) ;
74
89
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 ) ;
75
92
}
76
93
77
94
[ Test ( Description = "Open RDP with no credentials" ) ]
78
95
[ CancelAfter ( 30_000 ) ]
79
96
public async Task NoCredentials ( CancellationToken ct )
80
97
{
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" ) ;
82
99
100
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
83
101
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
84
102
_ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
85
103
. Returns ( Task . CompletedTask ) ;
86
104
await uriHandler . HandleUri ( input , ct ) ;
105
+ _mRdpConnector . Verify ( m => m . Connect ( It . IsAny < string > ( ) , It . IsAny < int > ( ) , ct ) , Times . Once ) ;
87
106
}
88
107
89
108
[ Test ( Description = "Unknown app slug" ) ]
90
109
[ CancelAfter ( 30_000 ) ]
91
110
public async Task UnknownApp ( CancellationToken ct )
92
111
{
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" ) ;
94
113
114
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
95
115
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
96
116
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "someapp" ) , ct ) )
97
117
. Returns ( Task . CompletedTask ) ;
98
118
await uriHandler . HandleUri ( input , ct ) ;
119
+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
99
120
}
100
121
101
122
[ Test ( Description = "Unknown agent name" ) ]
102
123
[ CancelAfter ( 30_000 ) ]
103
124
public async Task UnknownAgent ( CancellationToken ct )
104
125
{
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" ) ;
106
127
128
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
107
129
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
108
130
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "wrongagent" ) , ct ) )
109
131
. Returns ( Task . CompletedTask ) ;
110
132
await uriHandler . HandleUri ( input , ct ) ;
133
+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
111
134
}
112
135
113
136
[ Test ( Description = "Unknown workspace name" ) ]
114
137
[ CancelAfter ( 30_000 ) ]
115
138
public async Task UnknownWorkspace ( CancellationToken ct )
116
139
{
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" ) ;
118
141
142
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
119
143
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
120
144
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "wrongworkspace" ) , ct ) )
121
145
. Returns ( Task . CompletedTask ) ;
122
146
await uriHandler . HandleUri ( input , ct ) ;
147
+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
123
148
}
124
149
125
150
[ Test ( Description = "Malformed Query String" ) ]
126
151
[ CancelAfter ( 30_000 ) ]
127
152
public async Task MalformedQuery ( CancellationToken ct )
128
153
{
129
154
// 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?%&##" ) ;
131
156
157
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
132
158
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
133
159
// treated the same as if we just didn't include credentials
134
160
_ = _mRdpConnector . Setup ( m => m . Connect ( agent11 . Fqdn [ 0 ] , IRdpConnector . DefaultPort , ct ) )
135
161
. Returns ( Task . CompletedTask ) ;
136
162
await uriHandler . HandleUri ( input , ct ) ;
163
+ _mRdpConnector . Verify ( m => m . Connect ( It . IsAny < string > ( ) , It . IsAny < int > ( ) , ct ) , Times . Once ) ;
137
164
}
138
165
139
166
[ Test ( Description = "VPN not started" ) ]
140
167
[ CancelAfter ( 30_000 ) ]
141
168
public async Task VPNNotStarted ( CancellationToken ct )
142
169
{
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" ) ;
144
171
172
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
145
173
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( new RpcModel
146
174
{
147
175
VpnLifecycle = VpnLifecycle . Starting ,
@@ -150,29 +178,79 @@ public async Task VPNNotStarted(CancellationToken ct)
150
178
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsRegex ( "Coder Connect" ) , ct ) )
151
179
. Returns ( Task . CompletedTask ) ;
152
180
await uriHandler . HandleUri ( input , ct ) ;
181
+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
153
182
}
154
183
155
184
[ Test ( Description = "Wrong number of components" ) ]
156
185
[ CancelAfter ( 30_000 ) ]
157
186
public async Task UnknownNumComponents ( CancellationToken ct )
158
187
{
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" ) ;
160
189
190
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
161
191
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
162
192
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) )
163
193
. Returns ( Task . CompletedTask ) ;
164
194
await uriHandler . HandleUri ( input , ct ) ;
195
+ _mUserNotifier . Verify ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) , Times . Once ( ) ) ;
165
196
}
166
197
167
198
[ Test ( Description = "Unknown prefix" ) ]
168
199
[ CancelAfter ( 30_000 ) ]
169
200
public async Task UnknownPrefix ( CancellationToken ct )
170
201
{
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" ) ;
172
203
204
+ _mCredentialManager . Setup ( m => m . GetCachedCredentials ( ) ) . Returns ( credentialModel1 ) ;
173
205
_mRpcController . Setup ( m => m . GetState ( ) ) . Returns ( modelWithWorkspace1 ) ;
174
206
_mUserNotifier . Setup ( m => m . ShowErrorNotification ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , ct ) )
175
207
. Returns ( Task . CompletedTask ) ;
176
208
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 ( ) ) ;
177
255
}
178
256
}
0 commit comments