From 8a1b4a214c9db9ec385d660ac01ee7ae030817d7 Mon Sep 17 00:00:00 2001 From: Jeremy Walker Date: Wed, 28 Oct 2026 21:04:50 +0900 Subject: [PATCH] Skip impact map points for metrics without a user Issue and pull request metrics have no user when the GitHub author has no linked Exercism account. The map read the user's handle before checking for this, so it crashed. Those points now render nothing. Fixes EXERCISM-JS-4Y Co-Authored-By: Claude Opus 5.5 --- app/javascript/components/impact/map.tsx | 31 ++++++++++--------- .../javascript/components/impact/map.test.tsx | 21 +++++++++++++ 2 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 test/javascript/components/impact/map.test.tsx diff --git a/app/javascript/components/impact/map.tsx b/app/javascript/components/impact/map.tsx index 297f18a184..cd1d9a6287 100644 --- a/app/javascript/components/impact/map.tsx +++ b/app/javascript/components/impact/map.tsx @@ -62,12 +62,8 @@ const MetricPointUserWithTooltip = ({ }): JSX.Element => { if (!metric.user) return <> - const avatarRef = useRef(null) const content = ( -
+
{ const { t } = useAppTranslation('components/impact/map.tsx') + + // Metrics for actions by people without an Exercism account (or whose + // details are private) arrive without a user, so there is nothing to show. + const userMetricTypes = [ + 'publish_solution_metric', + 'open_issue_metric', + 'open_pull_request_metric', + 'merge_pull_request_metric', + ] + if (userMetricTypes.includes(metric.type) && !metric.user) return <> + switch (metric.type) { case 'sign_up_metric': - const iconRef = useRef(null) const content = ( -
+
{ return ( ) case 'open_issue_metric': return ( ) case 'open_pull_request_metric': return ( ) case 'merge_pull_request_metric': return ( ) default: diff --git a/test/javascript/components/impact/map.test.tsx b/test/javascript/components/impact/map.test.tsx new file mode 100644 index 0000000000..037db3b9be --- /dev/null +++ b/test/javascript/components/impact/map.test.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { render } from '@testing-library/react' +import '@testing-library/jest-dom/extend-expect' +import ImpactMap from '@/components/impact/map' +import { Metric } from '@/components/types' + +test('renders an open issue metric that has no user', () => { + const metric = { + id: 1, + type: 'open_issue_metric', + coordinates: [35.6897, 139.6895], + countryCode: 'jp', + countryName: 'Japan', + } as unknown as Metric + + const { container } = render() + + const point = container.querySelector('.metric-open_issue_metric') + expect(point).toBeInTheDocument() + expect(point).toBeEmptyDOMElement() +})