Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7ec16cf

Browse files
feat(site): add latency to the terminal (#7801)
1 parent0413ed0 commit7ec16cf

File tree

10 files changed

+222
-146
lines changed

10 files changed

+222
-146
lines changed
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import{Route,Routes}from"react-router-dom"
21
import{renderWithAuth}from"testHelpers/renderHelpers"
32
import{DashboardLayout}from"./DashboardLayout"
43
import*asAPIfrom"api/api"
@@ -10,12 +9,8 @@ test("Show the new Coder version notification", async () => {
109
version:"v0.12.9",
1110
url:"https://github.com/coder/coder/releases/tag/v0.12.9",
1211
})
13-
renderWithAuth(
14-
<Routes>
15-
<Routeelement={<DashboardLayout/>}>
16-
<Routeelement={<h1>Test page</h1>}/>
17-
</Route>
18-
</Routes>,
19-
)
12+
renderWithAuth(<DashboardLayout/>,{
13+
children:[{element:<h1>Test page</h1>}],
14+
})
2015
awaitscreen.findByTestId("update-check-snackbar")
2116
})

‎site/src/components/Navbar/NavbarView.tsx‎

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Drawer from "@mui/material/Drawer"
22
importIconButtonfrom"@mui/material/IconButton"
33
importListfrom"@mui/material/List"
44
importListItemfrom"@mui/material/ListItem"
5-
import{makeStyles,useTheme}from"@mui/styles"
5+
import{makeStyles}from"@mui/styles"
66
importMenuIconfrom"@mui/icons-material/Menu"
77
import{CoderIcon}from"components/Icons/CoderIcon"
88
import{FC,useRef,useState}from"react"
@@ -20,10 +20,9 @@ import KeyboardArrowDownOutlined from "@mui/icons-material/KeyboardArrowDownOutl
2020
import{ProxyContextValue}from"contexts/ProxyContext"
2121
import{displayError}from"components/GlobalSnackbar/utils"
2222
importDividerfrom"@mui/material/Divider"
23-
importHelpOutlinefrom"@mui/icons-material/HelpOutline"
24-
importTooltipfrom"@mui/material/Tooltip"
2523
importSkeletonfrom"@mui/material/Skeleton"
2624
import{BUTTON_SM_HEIGHT}from"theme/theme"
25+
import{ProxyStatusLatency}from"components/ProxyStatusLatency/ProxyStatusLatency"
2726

2827
exportconstUSERS_LINK=`/users?filter=${encodeURIComponent("status:active")}`
2928

@@ -232,7 +231,6 @@ const ProxyMenu: FC<{ proxyContextValue: ProxyContextValue }> = ({
232231
</Box>
233232
{selectedProxy.display_name}
234233
<ProxyStatusLatency
235-
proxy={selectedProxy}
236234
latency={latencies?.[selectedProxy.id]?.latencyMS}
237235
/>
238236
</Box>
@@ -277,10 +275,7 @@ const ProxyMenu: FC<{ proxyContextValue: ProxyContextValue }> = ({
277275
/>
278276
</Box>
279277
{proxy.display_name}
280-
<ProxyStatusLatency
281-
proxy={proxy}
282-
latency={latencies?.[proxy.id]?.latencyMS}
283-
/>
278+
<ProxyStatusLatencylatency={latencies?.[proxy.id]?.latencyMS}/>
284279
</Box>
285280
</MenuItem>
286281
))}
@@ -301,42 +296,6 @@ const ProxyMenu: FC<{ proxyContextValue: ProxyContextValue }> = ({
301296
)
302297
}
303298

304-
constProxyStatusLatency:FC<{proxy:TypesGen.Region;latency?:number}>=({
305-
proxy,
306-
latency,
307-
})=>{
308-
consttheme=useTheme()
309-
letcolor=theme.palette.success.light
310-
311-
if(!latency){
312-
return(
313-
<Tooltiptitle="Latency not available">
314-
<HelpOutline
315-
sx={{
316-
ml:"auto",
317-
fontSize:"14px !important",
318-
color:(theme)=>theme.palette.text.secondary,
319-
}}
320-
/>
321-
</Tooltip>
322-
)
323-
}
324-
325-
if(latency>=300){
326-
color=theme.palette.error.light
327-
}
328-
329-
if(!proxy.healthy||latency>=100){
330-
color=theme.palette.warning.light
331-
}
332-
333-
return(
334-
<Boxsx={{ color,fontSize:13,marginLeft:"auto"}}>
335-
{latency.toFixed(0)}ms
336-
</Box>
337-
)
338-
}
339-
340299
constuseStyles=makeStyles((theme)=>({
341300
root:{
342301
height:navHeight,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import{useTheme}from"@mui/material/styles"
2+
importHelpOutlinefrom"@mui/icons-material/HelpOutline"
3+
importBoxfrom"@mui/material/Box"
4+
importTooltipfrom"@mui/material/Tooltip"
5+
import{FC}from"react"
6+
import{getLatencyColor}from"utils/latency"
7+
8+
exportconstProxyStatusLatency:FC<{latency?:number}>=({ latency})=>{
9+
consttheme=useTheme()
10+
constcolor=getLatencyColor(theme,latency)
11+
12+
if(!latency){
13+
return(
14+
<Tooltiptitle="Latency not available">
15+
<HelpOutline
16+
sx={{
17+
ml:"auto",
18+
fontSize:"14px !important",
19+
color,
20+
}}
21+
/>
22+
</Tooltip>
23+
)
24+
}
25+
26+
return(
27+
<Boxsx={{ color,fontSize:13,marginLeft:"auto"}}>
28+
{latency.toFixed(0)}ms
29+
</Box>
30+
)
31+
}

‎site/src/components/Resources/AgentLatency.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
}from"components/Tooltips/HelpTooltip"
99
import{Stack}from"components/Stack/Stack"
1010
import{WorkspaceAgent,DERPRegion}from"api/typesGenerated"
11-
import{getLatencyColor}from"utils/colors"
11+
import{getLatencyColor}from"utils/latency"
1212

1313
constgetDisplayLatency=(theme:Theme,agent:WorkspaceAgent)=>{
1414
// Find the right latency to display

‎site/src/pages/TerminalPage/TerminalPage.test.tsx‎

Lines changed: 48 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@ import "jest-canvas-mock"
33
importWSfrom"jest-websocket-mock"
44
import{rest}from"msw"
55
import{
6-
MockPrimaryWorkspaceProxy,
7-
MockProxyLatencies,
6+
MockUser,
87
MockWorkspace,
98
MockWorkspaceAgent,
10-
MockWorkspaceProxies,
119
}from"testHelpers/entities"
1210
import{TextDecoder,TextEncoder}from"util"
1311
import{ReconnectingPTYRequest}from"../../api/types"
14-
import{history,render}from"../../testHelpers/renderHelpers"
12+
import{
13+
renderWithAuth,
14+
waitForLoaderToBeRemoved,
15+
}from"../../testHelpers/renderHelpers"
1516
import{server}from"../../testHelpers/server"
1617
importTerminalPage,{Language}from"./TerminalPage"
17-
import{Route,Routes}from"react-router-dom"
18-
import{ProxyContext}from"contexts/ProxyContext"
1918

2019
Object.defineProperty(window,"matchMedia",{
2120
writable:true,
@@ -35,56 +34,35 @@ Object.defineProperty(window, "TextEncoder", {
3534
value:TextEncoder,
3635
})
3736

38-
constrenderTerminal=()=>{
39-
//@emyrk using renderWithAuth would be best here, but I was unable to get it to work.
40-
returnrender(
41-
<Routes>
42-
<Route
43-
path="/:username/:workspace/terminal"
44-
element={
45-
<ProxyContext.Provider
46-
value={{
47-
proxyLatencies:MockProxyLatencies,
48-
proxy:{
49-
proxy:MockPrimaryWorkspaceProxy,
50-
preferredPathAppURL:"",
51-
preferredWildcardHostname:"",
52-
},
53-
proxies:MockWorkspaceProxies,
54-
isFetched:true,
55-
isLoading:false,
56-
setProxy:jest.fn(),
57-
clearProxy:jest.fn(),
58-
refetchProxyLatencies:jest.fn(),
59-
}}
60-
>
61-
<TerminalPage/>
62-
</ProxyContext.Provider>
63-
}
64-
/>
65-
</Routes>,
66-
)
37+
constrenderTerminal=async(
38+
route=`/${MockUser.username}/${MockWorkspace.name}/terminal`,
39+
)=>{
40+
constutils=renderWithAuth(<TerminalPage/>,{
41+
route,
42+
path:"/:username/:workspace/terminal",
43+
})
44+
awaitwaitForLoaderToBeRemoved()
45+
returnutils
6746
}
6847

6948
constexpectTerminalText=(container:HTMLElement,text:string)=>{
70-
returnwaitFor(()=>{
71-
constelements=container.getElementsByClassName("xterm-rows")
72-
if(elements.length===0){
73-
thrownewError("no xterm-rows")
74-
}
75-
constrow=elements[0]asHTMLDivElement
76-
if(!row.textContent){
77-
thrownewError("no text content")
78-
}
79-
expect(row.textContent).toContain(text)
80-
})
49+
returnwaitFor(
50+
()=>{
51+
constelements=container.getElementsByClassName("xterm-rows")
52+
if(elements.length===0){
53+
thrownewError("no xterm-rows")
54+
}
55+
constrow=elements[0]asHTMLDivElement
56+
if(!row.textContent){
57+
thrownewError("no text content")
58+
}
59+
expect(row.textContent).toContain(text)
60+
},
61+
{timeout:3_000},
62+
)
8163
}
8264

8365
describe("TerminalPage",()=>{
84-
beforeEach(()=>{
85-
history.push(`/some-user/${MockWorkspace.name}/terminal`)
86-
})
87-
8866
it("shows an error if fetching workspace fails",async()=>{
8967
// Given
9068
server.use(
@@ -97,7 +75,7 @@ describe("TerminalPage", () => {
9775
)
9876

9977
// When
100-
const{ container}=renderTerminal()
78+
const{ container}=awaitrenderTerminal()
10179

10280
// Then
10381
awaitexpectTerminalText(container,Language.workspaceErrorMessagePrefix)
@@ -112,67 +90,66 @@ describe("TerminalPage", () => {
11290
)
11391

11492
// When
115-
const{ container}=renderTerminal()
93+
const{ container}=awaitrenderTerminal()
11694

11795
// Then
11896
awaitexpectTerminalText(container,Language.websocketErrorMessagePrefix)
11997
})
12098

12199
it("renders data from the backend",async()=>{
122100
// Given
123-
constserver=newWS(
124-
"ws://localhost/api/v2/workspaceagents/"+MockWorkspaceAgent.id+"/pty",
101+
constws=newWS(
102+
`ws://localhost/api/v2/workspaceagents/${MockWorkspaceAgent.id}/pty`,
125103
)
126104
consttext="something to render"
127105

128106
// When
129-
const{ container}=renderTerminal()
107+
const{ container}=awaitrenderTerminal()
130108

131109
// Then
132-
awaitserver.connected
133-
server.send(text)
110+
awaitws.connected
111+
ws.send(text)
134112
awaitexpectTerminalText(container,text)
135-
server.close()
113+
ws.close()
136114
})
137115

138116
it("resizes on connect",async()=>{
139117
// Given
140-
constserver=newWS(
141-
"ws://localhost/api/v2/workspaceagents/"+MockWorkspaceAgent.id+"/pty",
118+
constws=newWS(
119+
`ws://localhost/api/v2/workspaceagents/${MockWorkspaceAgent.id}/pty`,
142120
)
143121

144122
// When
145-
renderTerminal()
123+
awaitrenderTerminal()
146124

147125
// Then
148-
awaitserver.connected
149-
constmsg=awaitserver.nextMessage
126+
awaitws.connected
127+
constmsg=awaitws.nextMessage
150128
constreq:ReconnectingPTYRequest=JSON.parse(
151129
newTextDecoder().decode(msgasUint8Array),
152130
)
153131

154132
expect(req.height).toBeGreaterThan(0)
155133
expect(req.width).toBeGreaterThan(0)
156-
server.close()
134+
ws.close()
157135
})
158136

159137
it("supports workspace.agent syntax",async()=>{
160138
// Given
161-
constserver=newWS(
162-
"ws://localhost/api/v2/workspaceagents/"+MockWorkspaceAgent.id+"/pty",
139+
constws=newWS(
140+
`ws://localhost/api/v2/workspaceagents/${MockWorkspaceAgent.id}/pty`,
163141
)
164142
consttext="something to render"
165143

166144
// When
167-
history.push(
145+
const{ container}=awaitrenderTerminal(
168146
`/some-user/${MockWorkspace.name}.${MockWorkspaceAgent.name}/terminal`,
169147
)
170-
const{ container}=renderTerminal()
171148

172149
// Then
173-
awaitserver.connected
174-
server.send(text)
150+
awaitws.connected
151+
ws.send(text)
175152
awaitexpectTerminalText(container,text)
176-
server.close()
153+
ws.close()
177154
})
178155
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp