Skip to content

Commit 759746c

Browse files
fix(site): update useAgentLogs to make it more testable and add more tests (coder#19126)
Take 2 Closes coder/internal#644 ## Changes made - Updated how `useAgentLogs` was defined to make it easier to inject specific data dependencies (basically making the hook more unit-testable) - Simplified the hook API to limit the amount of scope of data it needs to work - Added more test cases, and re-enabled the one test case we had previously disabled - Extracted our mock websocket code into a separate file, and added more methods to it - Updated all runtime code to accommodate new changes
1 parent d3bf506 commit 759746c

File tree

18 files changed

+475
-280
lines changed

18 files changed

+475
-280
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
}
5555
},
5656

57+
"tailwindCSS.classFunctions": ["cva", "cn"],
5758
"[css][html][markdown][yaml]": {
5859
"editor.defaultFormatter": "esbenp.prettier-vscode"
5960
},

site/src/components/Alert/ErrorAlert.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import type { FC } from "react";
44
import { Link } from "../Link/Link";
55
import { Alert, AlertDetail, type AlertProps } from "./Alert";
66

7-
export const ErrorAlert: FC<
7+
type ErrorAlertProps = Readonly<
88
Omit<AlertProps, "severity" | "children"> & { error: unknown }
9-
> = ({ error, ...alertProps }) => {
9+
>;
10+
11+
export const ErrorAlert: FC<ErrorAlertProps> = ({ error, ...alertProps }) => {
1012
const message = getErrorMessage(error, "Something went wrong.");
1113
const detail = getErrorDetail(error);
1214
const status = getErrorStatus(error);

site/src/components/Badge/Badge.stories.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ export const Warning: Story = {
2121
},
2222
};
2323

24+
export const Destructive: Story = {
25+
args: {
26+
variant: "destructive",
27+
},
28+
};
29+
30+
export const Info: Story = {
31+
args: {
32+
variant: "info",
33+
},
34+
};
35+
36+
export const Green: Story = {
37+
args: {
38+
variant: "green",
39+
},
40+
};
41+
2442
export const SmallWithIcon: Story = {
2543
args: {
2644
variant: "default",

site/src/components/Badge/Badge.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ const badgeVariants = cva(
2323
destructive:
2424
"border border-solid border-border-destructive bg-surface-red text-highlight-red shadow",
2525
green:
26-
"border border-solid border-surface-green bg-surface-green text-highlight-green shadow",
27-
info: "border border-solid border-surface-sky bg-surface-sky text-highlight-sky shadow",
26+
"border border-solid border-border-green bg-surface-green text-highlight-green shadow",
27+
info: "border border-solid border-border-sky bg-surface-sky text-highlight-sky shadow",
2828
},
2929
size: {
3030
xs: "text-2xs font-regular h-5 [&_svg]:hidden rounded px-1.5",
@@ -50,7 +50,7 @@ const badgeVariants = cva(
5050
defaultVariants: {
5151
variant: "default",
5252
size: "md",
53-
border: "solid",
53+
border: "none",
5454
hover: false,
5555
},
5656
},

site/src/components/Latency/Latency.stories.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Meta, StoryObj } from "@storybook/react-vite";
2+
import { screen, userEvent, within } from "storybook/test";
23
import { Latency } from "./Latency";
34

45
const meta: Meta<typeof Latency> = {
@@ -32,3 +33,19 @@ export const Loading: Story = {
3233
isLoading: true,
3334
},
3435
};
36+
37+
export const NoLatency: Story = {
38+
args: {
39+
latency: undefined,
40+
},
41+
42+
play: async ({ canvasElement }) => {
43+
const canvas = within(canvasElement);
44+
const tooltipTrigger = canvas.getByLabelText(/Latency not available/i);
45+
await userEvent.hover(tooltipTrigger);
46+
47+
// Need to await getting the tooltip because the tooltip doesn't open
48+
// immediately on hover
49+
await screen.findByRole("tooltip", { name: /Latency not available/i });
50+
},
51+
};

site/src/components/Latency/Latency.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,54 @@
11
import { useTheme } from "@emotion/react";
22
import CircularProgress from "@mui/material/CircularProgress";
33
import Tooltip from "@mui/material/Tooltip";
4-
import { visuallyHidden } from "@mui/utils";
54
import { Abbr } from "components/Abbr/Abbr";
65
import { CircleHelpIcon } from "lucide-react";
76
import type { FC } from "react";
7+
import { cn } from "utils/cn";
88
import { getLatencyColor } from "utils/latency";
99

1010
interface LatencyProps {
1111
latency?: number;
1212
isLoading?: boolean;
13-
size?: number;
13+
className?: string;
14+
iconClassName?: string;
1415
}
1516

1617
export const Latency: FC<LatencyProps> = ({
1718
latency,
1819
isLoading,
19-
size = 14,
20+
className,
21+
iconClassName,
2022
}) => {
2123
const theme = useTheme();
2224
// Always use the no latency color for loading.
2325
const color = getLatencyColor(theme, isLoading ? undefined : latency);
2426

2527
if (isLoading) {
2628
return (
27-
<Tooltip title="Loading latency...">
28-
<CircularProgress size={size} className="ml-auto" style={{ color }} />
29+
<Tooltip title="Loading latency..." className={className}>
30+
<CircularProgress
31+
className={cn("!size-icon-xs", iconClassName)}
32+
style={{ color }}
33+
/>
2934
</Tooltip>
3035
);
3136
}
3237

3338
if (!latency) {
34-
const notAvailableText = "Latency not available";
3539
return (
36-
<Tooltip title={notAvailableText}>
37-
<>
38-
<span css={{ ...visuallyHidden }}>{notAvailableText}</span>
39-
40-
<CircleHelpIcon className="ml-auto size-icon-sm" style={{ color }} />
41-
</>
40+
<Tooltip title="Latency not available" className={className}>
41+
<CircleHelpIcon
42+
className={cn("!size-icon-sm", iconClassName)}
43+
style={{ color }}
44+
/>
4245
</Tooltip>
4346
);
4447
}
4548

4649
return (
47-
<div className="ml-auto text-sm" style={{ color }}>
48-
<span css={{ ...visuallyHidden }}>Latency: </span>
50+
<div className={cn("text-sm", className)} style={{ color }}>
51+
<span className="sr-only">Latency: </span>
4952
{latency.toFixed(0)}
5053
<Abbr title="milliseconds">ms</Abbr>
5154
</div>

site/src/hooks/useEmbeddedMetadata.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,12 @@ export function makeUseEmbeddedMetadata(
229229
manager.getMetadata,
230230
);
231231

232-
// biome-ignore lint/correctness/useExhaustiveDependencies(manager.clearMetadataByKey): baked into containing hook
233232
const stableMetadataResult = useMemo<UseEmbeddedMetadataResult>(() => {
234233
return {
235234
metadata,
236235
clearMetadataByKey: manager.clearMetadataByKey,
237236
};
238-
}, [metadata]);
237+
}, [manager, metadata]);
239238

240239
return stableMetadataResult;
241240
};

site/src/index.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
--surface-purple: 251 91% 95%;
3333
--border-default: 240 6% 90%;
3434
--border-success: 142 76% 36%;
35+
--border-sky: 203 90% 40%;
36+
--border-green: 138 82% 82%;
3537
--border-warning: 30.66, 97.16%, 72.35%;
3638
--border-destructive: 0 84% 60%;
3739
--border-hover: 240 5% 34%;
@@ -75,6 +77,8 @@
7577
--border-success: 142 76% 36%;
7678
--border-warning: 30.66, 97.16%, 72.35%;
7779
--border-destructive: 0 91% 71%;
80+
--border-sky: 194 90% 62%;
81+
--border-green: 143 77% 87%;
7882
--border-hover: 240, 5%, 34%;
7983
--overlay-default: 240 10% 4% / 80%;
8084
--highlight-purple: 252 95% 85%;

site/src/modules/dashboard/Navbar/MobileMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ const ProxySettingsSub: FC<ProxySettingsSubProps> = ({ proxyContextValue }) => {
162162
<img className="w-4 h-4" src={p.icon_url} alt={p.name} />
163163
{p.display_name || p.name}
164164
{latency ? (
165-
<Latency latency={latency.latencyMS} />
165+
<Latency className="ml-auto" latency={latency.latencyMS} />
166166
) : (
167167
<CircleHelpIcon className="ml-auto" />
168168
)}

site/src/modules/dashboard/Navbar/ProxyMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ export const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
9292
<Latency
9393
latency={latencies?.[selectedProxy.id]?.latencyMS}
9494
isLoading={proxyLatencyLoading(selectedProxy)}
95-
size={24}
9695
/>
9796
</>
9897
) : (
@@ -191,6 +190,7 @@ export const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
191190
{proxy.display_name}
192191

193192
<Latency
193+
className="ml-auto"
194194
latency={latencies?.[proxy.id]?.latencyMS}
195195
isLoading={proxyLatencyLoading(proxy)}
196196
/>

0 commit comments

Comments
 (0)