mirror of
https://github.com/apache/superset.git
synced 2026-04-17 23:25:05 +00:00
fix(chart): Display better hover text for country map charts (#36323)
Co-authored-by: askinner1 <144823527+askinner1@users.noreply.github.com> Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
This commit is contained in:
165
superset-frontend/package-lock.json
generated
165
superset-frontend/package-lock.json
generated
@@ -5333,7 +5333,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-5.2.7.tgz",
|
||||
"integrity": "sha512-tnB9NNund9TwIym8/7DMJe573nlPEQb+fKUV5GL8TBYXjIhDvL0D7mgmNVNQUPhXp+R7RylQeiBdkA4EbOHPGQ==",
|
||||
"license": "OFL-1.1",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
@@ -10199,85 +10198,6 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz",
|
||||
"integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
|
||||
"integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^3.0.0",
|
||||
"@octokit/graphql": "^5.0.0",
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz",
|
||||
"integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/types": "^9.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz",
|
||||
"integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "18.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz",
|
||||
@@ -10355,55 +10275,6 @@
|
||||
"@octokit/openapi-types": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "6.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz",
|
||||
"integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^7.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz",
|
||||
"integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/types": "^9.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "20.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz",
|
||||
@@ -19568,8 +19439,7 @@
|
||||
"version": "1.43.4",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.4.tgz",
|
||||
"integrity": "sha512-8hAxVfo2ImICd69BWlZwZlxe9rxDGDjuUhh+WeWgGDvfBCE+r3lkynkQvIovDz4jcMi8O7bsEaFygaDT+h9sBA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "7.4.1",
|
||||
@@ -24326,24 +24196,6 @@
|
||||
"integrity": "sha512-O/gRkjWULp3xVX8K85V0H3tsSGole0WYt77KVpGZO2xTGLuVFuvE6JIsIli3fvFHCYBhGFn/8OHEEyMYF+QehA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/dateformat": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.2.tgz",
|
||||
@@ -64956,15 +64808,6 @@
|
||||
"tinycolor2": "*"
|
||||
}
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/@fontsource/fira-code": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-5.2.6.tgz",
|
||||
"integrity": "sha512-wCkIpPm0BqlkCPLYeY4Vui96ODmVUV0/GpEe3OfJ4v8EJn/BF2SlyxvarFsTs1CKiGjrO2cXlIZbBrKi9F+hUQ==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/@types/lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz",
|
||||
@@ -64988,12 +64831,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/ace-builds": {
|
||||
"version": "1.43.3",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.3.tgz",
|
||||
"integrity": "sha512-MCl9rALmXwIty/4Qboijo/yNysx1r6hBTzG+6n/TiOm5LFhZpEvEIcIITPFiEOEFDfgBOEmxu+a4f54LEFM6Sg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/d3-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@apache-superset/core": "*",
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
.superset-legacy-chart-country-map svg {
|
||||
background-color: #feffff;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .background {
|
||||
fill: rgba(255, 255, 255, 0);
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .map-layer {
|
||||
fill: #fff;
|
||||
stroke: #aaa;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .effect-layer {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .text-layer {
|
||||
color: #333333;
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map text.result-text {
|
||||
font-weight: 300;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map text.big-text {
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map path.region {
|
||||
cursor: pointer;
|
||||
stroke: #eee;
|
||||
}
|
||||
@@ -90,15 +90,7 @@ function CountryMap(element, props) {
|
||||
.attr('height', height);
|
||||
const g = svg.append('g');
|
||||
const mapLayer = g.append('g').classed('map-layer', true);
|
||||
const textLayer = g
|
||||
.append('g')
|
||||
.classed('text-layer', true)
|
||||
.attr('transform', `translate(${width / 2}, 45)`);
|
||||
const bigText = textLayer.append('text').classed('big-text', true);
|
||||
const resultText = textLayer
|
||||
.append('text')
|
||||
.classed('result-text', true)
|
||||
.attr('dy', '1em');
|
||||
const hoverPopup = div.append('div').attr('class', 'hover-popup');
|
||||
|
||||
let centered;
|
||||
|
||||
@@ -128,45 +120,18 @@ function CountryMap(element, props) {
|
||||
'transform',
|
||||
`translate(${halfWidth},${halfHeight})scale(${k})translate(${-x},${-y})`,
|
||||
);
|
||||
textLayer
|
||||
.style('opacity', 0)
|
||||
.attr(
|
||||
'transform',
|
||||
`translate(0,0)translate(${x},${hasCenter ? y - 5 : 45})`,
|
||||
)
|
||||
.transition()
|
||||
.duration(750)
|
||||
.style('opacity', 1);
|
||||
bigText
|
||||
.transition()
|
||||
.duration(750)
|
||||
.style('font-size', hasCenter ? 6 : 16);
|
||||
resultText
|
||||
.transition()
|
||||
.duration(750)
|
||||
.style('font-size', hasCenter ? 16 : 24);
|
||||
};
|
||||
|
||||
backgroundRect.on('click', clicked);
|
||||
|
||||
const selectAndDisplayNameOfRegion = function selectAndDisplayNameOfRegion(
|
||||
feature,
|
||||
) {
|
||||
let name = '';
|
||||
const getNameOfRegion = function getNameOfRegion(feature) {
|
||||
if (feature && feature.properties) {
|
||||
if (feature.properties.ID_2) {
|
||||
name = feature.properties.NAME_2;
|
||||
} else {
|
||||
name = feature.properties.NAME_1;
|
||||
return feature.properties.NAME_2;
|
||||
}
|
||||
return feature.properties.NAME_1;
|
||||
}
|
||||
bigText.text(name);
|
||||
};
|
||||
|
||||
const updateMetrics = function updateMetrics(region) {
|
||||
if (region.length > 0) {
|
||||
resultText.text(format(region[0].metric));
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const mouseenter = function mouseenter(d) {
|
||||
@@ -176,17 +141,31 @@ function CountryMap(element, props) {
|
||||
c = d3.rgb(c).darker().toString();
|
||||
}
|
||||
d3.select(this).style('fill', c);
|
||||
selectAndDisplayNameOfRegion(d);
|
||||
// Display information popup
|
||||
const result = data.filter(
|
||||
region => region.country_id === d.properties.ISO,
|
||||
);
|
||||
updateMetrics(result);
|
||||
|
||||
const position = d3.mouse(svg.node());
|
||||
hoverPopup
|
||||
.style('display', 'block')
|
||||
.style('top', `${position[1] + 30}px`)
|
||||
.style('left', `${position[0]}px`)
|
||||
.html(
|
||||
`<div><strong>${getNameOfRegion(d)}</strong><br>${result.length > 0 ? format(result[0].metric) : ''}</div>`,
|
||||
);
|
||||
};
|
||||
|
||||
const mousemove = function mousemove() {
|
||||
const position = d3.mouse(svg.node());
|
||||
hoverPopup
|
||||
.style('top', `${position[1] + 30}px`)
|
||||
.style('left', `${position[0]}px`);
|
||||
};
|
||||
|
||||
const mouseout = function mouseout() {
|
||||
d3.select(this).style('fill', colorFn);
|
||||
bigText.text('');
|
||||
resultText.text('');
|
||||
hoverPopup.style('display', 'none');
|
||||
};
|
||||
|
||||
function drawMap(mapData) {
|
||||
@@ -225,6 +204,7 @@ function CountryMap(element, props) {
|
||||
.attr('vector-effect', 'non-scaling-stroke')
|
||||
.style('fill', colorFn)
|
||||
.on('mouseenter', mouseenter)
|
||||
.on('mousemove', mousemove)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', clicked);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import Component from './CountryMap';
|
||||
|
||||
const ReactComponent = reactify(Component);
|
||||
|
||||
const CountryMap = ({ className, ...otherProps }) => (
|
||||
const CountryMap = ({ className = '', ...otherProps }) => (
|
||||
<div className={className}>
|
||||
<ReactComponent {...otherProps} />
|
||||
</div>
|
||||
@@ -43,33 +43,29 @@ export default styled(CountryMap)`
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .hover-popup {
|
||||
position: absolute;
|
||||
color: ${theme.colorTextSecondary};
|
||||
display: none;
|
||||
padding: 4px;
|
||||
border-radius: 1px;
|
||||
background-color: ${theme.colorBgElevated};
|
||||
box-shadow: ${theme.boxShadow};
|
||||
font-size: 12px;
|
||||
border: 1px solid ${theme.colorBorder};
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .map-layer {
|
||||
fill: ${theme.colorBgContainer};
|
||||
stroke: ${theme.colorBorderSecondary};
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .effect-layer {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map .text-layer {
|
||||
color: ${theme.colorText};
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map text.result-text {
|
||||
fill: ${theme.colorText};
|
||||
font-weight: ${theme.fontWeightLight};
|
||||
font-size: ${theme.fontSizeXL}px;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map text.big-text {
|
||||
fill: ${theme.colorText};
|
||||
font-weight: ${theme.fontWeightStrong};
|
||||
font-size: ${theme.fontSizeLG}px;
|
||||
}
|
||||
|
||||
.superset-legacy-chart-country-map path.region {
|
||||
cursor: pointer;
|
||||
stroke: ${theme.colorSplit};
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import d3 from 'd3';
|
||||
import ReactCountryMap from '../src/ReactCountryMap';
|
||||
|
||||
jest.spyOn(d3, 'json');
|
||||
|
||||
type Projection = ((...args: unknown[]) => void) & {
|
||||
scale: () => Projection;
|
||||
center: () => Projection;
|
||||
translate: () => Projection;
|
||||
};
|
||||
|
||||
type PathFn = (() => string) & {
|
||||
projection: jest.Mock;
|
||||
bounds: jest.Mock<[[number, number], [number, number]]>;
|
||||
centroid: jest.Mock<[number, number]>;
|
||||
};
|
||||
|
||||
const mockPath: PathFn = jest.fn(() => 'M10 10 L20 20') as unknown as PathFn;
|
||||
mockPath.projection = jest.fn();
|
||||
mockPath.bounds = jest.fn(() => [
|
||||
[0, 0],
|
||||
[100, 100],
|
||||
]);
|
||||
mockPath.centroid = jest.fn(() => [50, 50]);
|
||||
|
||||
jest.spyOn(d3.geo, 'path').mockImplementation(() => mockPath);
|
||||
|
||||
// Mock d3.geo.mercator
|
||||
jest.spyOn(d3.geo, 'mercator').mockImplementation(() => {
|
||||
const proj = (() => {}) as Projection;
|
||||
proj.scale = () => proj;
|
||||
proj.center = () => proj;
|
||||
proj.translate = () => proj;
|
||||
return proj;
|
||||
});
|
||||
|
||||
// Mock d3.mouse
|
||||
jest.spyOn(d3, 'mouse').mockReturnValue([100, 50]);
|
||||
|
||||
const mockMapData = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: { ISO: 'CAN', NAME_1: 'Canada' },
|
||||
geometry: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
type D3JsonCallback = (error: Error | null, data: unknown) => void;
|
||||
|
||||
describe('CountryMap (legacy d3)', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders a map after d3.json loads data', async () => {
|
||||
d3.json.mockImplementation((_url: string, cb: D3JsonCallback) =>
|
||||
cb(null, mockMapData),
|
||||
);
|
||||
|
||||
render(
|
||||
<ReactCountryMap
|
||||
width={500}
|
||||
height={300}
|
||||
data={[{ country_id: 'CAN', metric: 100 }]}
|
||||
country="canada"
|
||||
linearColorScheme="bnbColors"
|
||||
colorScheme=""
|
||||
numberFormat=".2f"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(d3.json).toHaveBeenCalledTimes(1);
|
||||
|
||||
const region = document.querySelector('path.region');
|
||||
expect(region).not.toBeNull();
|
||||
});
|
||||
|
||||
it('shows tooltip on mouseenter/mousemove/mouseout', async () => {
|
||||
d3.json.mockImplementation((_url: string, cb: D3JsonCallback) =>
|
||||
cb(null, mockMapData),
|
||||
);
|
||||
|
||||
render(
|
||||
<ReactCountryMap
|
||||
width={500}
|
||||
height={300}
|
||||
data={[{ country_id: 'CAN', metric: 100 }]}
|
||||
country="canada"
|
||||
linearColorScheme="bnbColors"
|
||||
colorScheme=""
|
||||
/>,
|
||||
);
|
||||
|
||||
const region = document.querySelector('path.region');
|
||||
expect(region).not.toBeNull();
|
||||
|
||||
const popup = document.querySelector('.hover-popup');
|
||||
expect(popup).not.toBeNull();
|
||||
|
||||
fireEvent.mouseEnter(region!);
|
||||
expect(popup!).toHaveStyle({ display: 'block' });
|
||||
|
||||
fireEvent.mouseOut(region!);
|
||||
expect(popup!).toHaveStyle({ display: 'none' });
|
||||
});
|
||||
|
||||
it('shows tooltip on mouseenter/mousemove/mouseout', async () => {
|
||||
d3.json.mockImplementation((_url: string, cb: D3JsonCallback) =>
|
||||
cb(null, mockMapData),
|
||||
);
|
||||
|
||||
render(
|
||||
<ReactCountryMap
|
||||
width={500}
|
||||
height={300}
|
||||
data={[{ country_id: 'CAN', metric: 100 }]}
|
||||
country="canada"
|
||||
linearColorScheme="bnbColors"
|
||||
colorScheme=""
|
||||
/>,
|
||||
);
|
||||
|
||||
const region = document.querySelector('path.region');
|
||||
expect(region).not.toBeNull();
|
||||
|
||||
const popup = document.querySelector('.hover-popup');
|
||||
expect(popup).not.toBeNull();
|
||||
|
||||
fireEvent.mouseEnter(region!);
|
||||
expect(popup!).toHaveStyle({ display: 'block' });
|
||||
|
||||
fireEvent.mouseOut(region!);
|
||||
expect(popup!).toHaveStyle({ display: 'none' });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user