From 5634f4d9030c9c2799ca2f806012f7cad67a54b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:44:21 +0000 Subject: [PATCH 1/3] Initial plan From 6b365e898e42f7d6f71cb1643a473017c63c4920 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:57:10 +0000 Subject: [PATCH 2/3] Add syntax highlighting to CodeBlock component using react-syntax-highlighter Co-authored-by: msaroufim <3282513+msaroufim@users.noreply.github.com> --- frontend/package-lock.json | 287 ++++++++++++++++++ frontend/package.json | 2 + .../components/codeblock/CodeBlock.test.tsx | 54 ++++ .../src/components/codeblock/CodeBlock.tsx | 38 ++- .../pages/leaderboard/Leaderboard.test.tsx | 9 +- .../src/pages/leaderboard/Leaderboard.tsx | 2 +- 6 files changed, 376 insertions(+), 16 deletions(-) create mode 100644 frontend/src/components/codeblock/CodeBlock.test.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 45d02a5..5f10118 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", + "@types/react-syntax-highlighter": "^15.5.13", "dayjs": "^1.11.13", "imurmurhash": "^0.1.4", "react": "^19.1.0", @@ -19,6 +20,7 @@ "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-router-dom": "^7.6.2", + "react-syntax-highlighter": "^15.6.6", "rehype-raw": "^7.0.0", "zustand": "^5.0.7" }, @@ -2031,6 +2033,15 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/react-syntax-highlighter": { + "version": "15.5.13", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", + "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.12", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", @@ -3299,6 +3310,19 @@ "reusify": "^1.0.4" } }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3363,6 +3387,14 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3580,6 +3612,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/highlightjs-vue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", + "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", + "license": "CC0-1.0" + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -4001,6 +4048,20 @@ "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", "dev": true }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "license": "MIT", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -4947,6 +5008,15 @@ "dev": true, "peer": true }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5103,6 +5173,23 @@ "react-dom": ">=18" } }, + "node_modules/react-syntax-highlighter": { + "version": "15.6.6", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", + "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.4.1", + "highlightjs-vue": "^1.0.0", + "lowlight": "^1.17.0", + "prismjs": "^1.30.0", + "refractor": "^3.6.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -5131,6 +5218,197 @@ "node": ">=8" } }, + "node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "license": "MIT", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/refractor/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/refractor/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/refractor/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -6211,6 +6489,15 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 8977493..dc90aaa 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", + "@types/react-syntax-highlighter": "^15.5.13", "dayjs": "^1.11.13", "imurmurhash": "^0.1.4", "react": "^19.1.0", @@ -23,6 +24,7 @@ "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-router-dom": "^7.6.2", + "react-syntax-highlighter": "^15.6.6", "rehype-raw": "^7.0.0", "zustand": "^5.0.7" }, diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx new file mode 100644 index 0000000..c3963a5 --- /dev/null +++ b/frontend/src/components/codeblock/CodeBlock.test.tsx @@ -0,0 +1,54 @@ +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { describe, it, expect, vi } from "vitest"; +import CodeBlock from "./CodeBlock"; + +// Mock clipboard API +Object.assign(navigator, { + clipboard: { + writeText: vi.fn(() => Promise.resolve()), + }, +}); + +describe("CodeBlock", () => { + const sampleCode = `function hello() { + console.log("Hello, world!"); +}`; + + it("renders code content", () => { + render(); + expect(screen.getByText(/Hello, world!/)).toBeInTheDocument(); + }); + + it("renders with syntax highlighting", () => { + render(); + // Check that syntax highlighter is applied - it should create a pre element + const preElement = screen.getByRole("button").closest("[data-testid]") || document.querySelector("pre"); + expect(preElement || screen.getByText(/Hello, world!/).closest("pre")).toBeInTheDocument(); + }); + + it("copies code to clipboard when copy button is clicked", async () => { + const writeTextSpy = vi.spyOn(navigator.clipboard, "writeText"); + + render(); + + const copyButton = screen.getByRole("button"); + fireEvent.click(copyButton); + + expect(writeTextSpy).toHaveBeenCalledWith(sampleCode); + + // Check tooltip changes to "Copied!" - it's in aria-label + await waitFor(() => { + expect(copyButton).toHaveAttribute("aria-label", "Copied!"); + }); + }); + + it("accepts language prop for syntax highlighting", () => { + render(); + expect(screen.getByText(/Hello/)).toBeInTheDocument(); + }); + + it("defaults to text language when no language specified", () => { + render(); + expect(screen.getByText("plain text")).toBeInTheDocument(); + }); +}); diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx index b5061a3..92b5686 100644 --- a/frontend/src/components/codeblock/CodeBlock.tsx +++ b/frontend/src/components/codeblock/CodeBlock.tsx @@ -3,17 +3,15 @@ import { Box, IconButton, Tooltip, - Typography, useTheme, - type SxProps, - type Theme, } from "@mui/material"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; -import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import ExpandLessIcon from "@mui/icons-material/ExpandLess"; +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism"; interface CodeBlockProps { code: string; + language?: string; maxHeight?: number | string; } @@ -34,7 +32,7 @@ const styles = { }, }; -export default function CodeBlock({ code }: CodeBlockProps) { +export default function CodeBlock({ code, language = "text" }: CodeBlockProps) { const [copied, setCopied] = useState(false); const theme = useTheme(); @@ -56,11 +54,9 @@ export default function CodeBlock({ code }: CodeBlockProps) { - {/* Scrollable Code */} + {/* Scrollable Code with Syntax Highlighting */} - {code} + + {code} + ); diff --git a/frontend/src/pages/leaderboard/Leaderboard.test.tsx b/frontend/src/pages/leaderboard/Leaderboard.test.tsx index 52bb457..cdfdb19 100644 --- a/frontend/src/pages/leaderboard/Leaderboard.test.tsx +++ b/frontend/src/pages/leaderboard/Leaderboard.test.tsx @@ -103,7 +103,8 @@ describe("Leaderboard", () => { // Switch to Reference tab before asserting its content fireEvent.click(referenceTab); expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument(); - expect(screen.getByText(mockReference)).toBeInTheDocument(); + expect(screen.getByText(/import/)).toBeInTheDocument(); + expect(screen.getByText(/torch/)).toBeInTheDocument(); }); it("shows loading state", () => { @@ -302,7 +303,8 @@ describe("Leaderboard", () => { // Reference codeblock should be visible expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument(); - expect(screen.getByText(mockReference)).toBeInTheDocument(); + expect(screen.getByText(/import/)).toBeInTheDocument(); + expect(screen.getByText(/torch/)).toBeInTheDocument(); }); // -------------------- Tabs behavior (switching) -------------------- @@ -343,7 +345,8 @@ describe("Leaderboard", () => { // Switch to Reference tab fireEvent.click(screen.getByRole("tab", { name: /Reference/i })); expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument(); - expect(screen.getByText(mockReference)).toBeInTheDocument(); + expect(screen.getByText(/import/)).toBeInTheDocument(); + expect(screen.getByText(/torch/)).toBeInTheDocument(); // Switch back to Rankings tab fireEvent.click(screen.getByRole("tab", { name: /Rankings/i })); diff --git a/frontend/src/pages/leaderboard/Leaderboard.tsx b/frontend/src/pages/leaderboard/Leaderboard.tsx index 5860de4..d428bea 100644 --- a/frontend/src/pages/leaderboard/Leaderboard.tsx +++ b/frontend/src/pages/leaderboard/Leaderboard.tsx @@ -176,7 +176,7 @@ export default function Leaderboard() { Reference Implementation - + From 08207bf97d63a503b313abf35ec24f91255c07b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:17:34 +0000 Subject: [PATCH 3/3] Simplify CodeBlock component for Python-only syntax highlighting Co-authored-by: msaroufim <3282513+msaroufim@users.noreply.github.com> --- .../src/components/codeblock/CodeBlock.test.tsx | 13 +++++-------- frontend/src/components/codeblock/CodeBlock.tsx | 5 ++--- frontend/src/pages/leaderboard/Leaderboard.tsx | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx index c3963a5..60a5fd5 100644 --- a/frontend/src/components/codeblock/CodeBlock.test.tsx +++ b/frontend/src/components/codeblock/CodeBlock.test.tsx @@ -19,8 +19,8 @@ describe("CodeBlock", () => { expect(screen.getByText(/Hello, world!/)).toBeInTheDocument(); }); - it("renders with syntax highlighting", () => { - render(); + it("renders with Python syntax highlighting", () => { + render(); // Check that syntax highlighter is applied - it should create a pre element const preElement = screen.getByRole("button").closest("[data-testid]") || document.querySelector("pre"); expect(preElement || screen.getByText(/Hello, world!/).closest("pre")).toBeInTheDocument(); @@ -42,13 +42,10 @@ describe("CodeBlock", () => { }); }); - it("accepts language prop for syntax highlighting", () => { - render(); + it("handles Python code properly", () => { + render(); expect(screen.getByText(/Hello/)).toBeInTheDocument(); }); - it("defaults to text language when no language specified", () => { - render(); - expect(screen.getByText("plain text")).toBeInTheDocument(); - }); + }); diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx index 92b5686..f2dab23 100644 --- a/frontend/src/components/codeblock/CodeBlock.tsx +++ b/frontend/src/components/codeblock/CodeBlock.tsx @@ -11,7 +11,6 @@ import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism"; interface CodeBlockProps { code: string; - language?: string; maxHeight?: number | string; } @@ -32,7 +31,7 @@ const styles = { }, }; -export default function CodeBlock({ code, language = "text" }: CodeBlockProps) { +export default function CodeBlock({ code }: CodeBlockProps) { const [copied, setCopied] = useState(false); const theme = useTheme(); @@ -76,7 +75,7 @@ export default function CodeBlock({ code, language = "text" }: CodeBlockProps) { }} > Reference Implementation - +