@@ -64,6 +64,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
64
64
// reconnecting-pty proxy server we want to test is mounted.
65
65
client := appDetails .AppClient (t )
66
66
testReconnectingPTY (ctx , t , client , appDetails .Agent .ID , "" )
67
+ assertWorkspaceLastUsedAtUpdated (t , client , appDetails )
67
68
})
68
69
69
70
t .Run ("SignedTokenQueryParameter" , func (t * testing.T ) {
@@ -92,6 +93,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
92
93
// Make an unauthenticated client.
93
94
unauthedAppClient := codersdk .New (appDetails .AppClient (t ).URL )
94
95
testReconnectingPTY (ctx , t , unauthedAppClient , appDetails .Agent .ID , issueRes .SignedToken )
96
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
95
97
})
96
98
})
97
99
@@ -117,6 +119,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
117
119
body , err := io .ReadAll (resp .Body )
118
120
require .NoError (t , err )
119
121
require .Contains (t , string (body ), "Path-based applications are disabled" )
122
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
120
123
})
121
124
122
125
t .Run ("LoginWithoutAuthOnPrimary" , func (t * testing.T ) {
@@ -142,6 +145,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
142
145
require .NoError (t , err )
143
146
require .True (t , loc .Query ().Has ("message" ))
144
147
require .True (t , loc .Query ().Has ("redirect" ))
148
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
145
149
})
146
150
147
151
t .Run ("LoginWithoutAuthOnProxy" , func (t * testing.T ) {
@@ -179,6 +183,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
179
183
// request is getting stripped.
180
184
require .Equal (t , u .Path , redirectURI .Path + "/" )
181
185
require .Equal (t , u .RawQuery , redirectURI .RawQuery )
186
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
182
187
})
183
188
184
189
t .Run ("NoAccessShould404" , func (t * testing.T ) {
@@ -195,6 +200,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
195
200
require .NoError (t , err )
196
201
defer resp .Body .Close ()
197
202
require .Equal (t , http .StatusNotFound , resp .StatusCode )
203
+ assertWorkspaceLastUsedAtNotUpdated (t , appDetails .AppClient (t ), appDetails )
198
204
})
199
205
200
206
t .Run ("RedirectsWithSlash" , func (t * testing.T ) {
@@ -209,6 +215,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
209
215
require .NoError (t , err )
210
216
defer resp .Body .Close ()
211
217
require .Equal (t , http .StatusTemporaryRedirect , resp .StatusCode )
218
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
212
219
})
213
220
214
221
t .Run ("RedirectsWithQuery" , func (t * testing.T ) {
@@ -226,6 +233,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
226
233
loc , err := resp .Location ()
227
234
require .NoError (t , err )
228
235
require .Equal (t , proxyTestAppQuery , loc .RawQuery )
236
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
229
237
})
230
238
231
239
t .Run ("Proxies" , func (t * testing.T ) {
@@ -267,6 +275,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
267
275
require .NoError (t , err )
268
276
require .Equal (t , proxyTestAppBody , string (body ))
269
277
require .Equal (t , http .StatusOK , resp .StatusCode )
278
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
270
279
})
271
280
272
281
t .Run ("ProxiesHTTPS" , func (t * testing.T ) {
@@ -312,6 +321,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
312
321
require .NoError (t , err )
313
322
require .Equal (t , proxyTestAppBody , string (body ))
314
323
require .Equal (t , http .StatusOK , resp .StatusCode )
324
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
315
325
})
316
326
317
327
t .Run ("BlocksMe" , func (t * testing.T ) {
@@ -331,6 +341,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
331
341
body , err := io .ReadAll (resp .Body )
332
342
require .NoError (t , err )
333
343
require .Contains (t , string (body ), "must be accessed with the full username, not @me" )
344
+ assertWorkspaceLastUsedAtNotUpdated (t , appDetails .AppClient (t ), appDetails )
334
345
})
335
346
336
347
t .Run ("ForwardsIP" , func (t * testing.T ) {
@@ -349,6 +360,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
349
360
require .Equal (t , proxyTestAppBody , string (body ))
350
361
require .Equal (t , http .StatusOK , resp .StatusCode )
351
362
require .Equal (t , "1.1.1.1,127.0.0.1" , resp .Header .Get ("X-Forwarded-For" ))
363
+ assertWorkspaceLastUsedAtUpdated (t , appDetails .AppClient (t ), appDetails )
352
364
})
353
365
354
366
t .Run ("ProxyError" , func (t * testing.T ) {
@@ -361,6 +373,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
361
373
require .NoError (t , err )
362
374
defer resp .Body .Close ()
363
375
require .Equal (t , http .StatusBadGateway , resp .StatusCode )
376
+ assertWorkspaceLastUsedAtNotUpdated (t , appDetails .AppClient (t ), appDetails )
364
377
})
365
378
366
379
t .Run ("NoProxyPort" , func (t * testing.T ) {
@@ -375,6 +388,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
375
388
// TODO(@deansheather): This should be 400. There's a todo in the
376
389
// resolve request code to fix this.
377
390
require .Equal (t , http .StatusInternalServerError , resp .StatusCode )
391
+ assertWorkspaceLastUsedAtNotUpdated (t , appDetails .AppClient (t ), appDetails )
378
392
})
379
393
})
380
394
@@ -548,6 +562,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
548
562
require .NoError (t , err )
549
563
resp .Body .Close ()
550
564
require .Equal (t , http .StatusOK , resp .StatusCode )
565
+ assertWorkspaceLastUsedAtUpdated (t , appClient , appDetails )
551
566
})
552
567
}
553
568
})
@@ -1549,3 +1564,23 @@ func testReconnectingPTY(ctx context.Context, t *testing.T, client *codersdk.Cli
1549
1564
// Ensure the connection closes.
1550
1565
require .ErrorIs (t , tr .ReadUntil (ctx , nil ), io .EOF )
1551
1566
}
1567
+
1568
+ // Accessing an app should update the workspace's LastUsedAt.
1569
+ func assertWorkspaceLastUsedAtUpdated (t testing.TB , client * codersdk.Client , details * Details ) {
1570
+ t .Helper ()
1571
+
1572
+ details .FlushStats ()
1573
+ ws , err := client .Workspace (context .Background (), details .Workspace .ID )
1574
+ require .NoError (t , err )
1575
+ require .Greater (t , ws .UpdatedAt , details .Workspace .UpdatedAt , "workspace last used at not updated when it should have been" )
1576
+ }
1577
+
1578
+ // Except when it sometimes shouldn't (e.g. no access)
1579
+ func assertWorkspaceLastUsedAtNotUpdated (t testing.TB , client * codersdk.Client , details * Details ) {
1580
+ t .Helper ()
1581
+
1582
+ details .FlushStats ()
1583
+ ws , err := client .Workspace (context .Background (), details .Workspace .ID )
1584
+ require .NoError (t , err )
1585
+ require .Equal (t , ws .UpdatedAt , details .Workspace .UpdatedAt , "workspace last used at updated when it shouldn't have been" )
1586
+ }
0 commit comments