@@ -1430,6 +1430,103 @@ describe('map plots', function() {
14301430 }
14311431} ) ;
14321432
1433+ describe ( 'map auto-fit' , ( ) => {
1434+ let gd ;
1435+
1436+ beforeEach ( ( ) => {
1437+ gd = createGraphDiv ( ) ;
1438+ } ) ;
1439+ afterEach ( ( ) => {
1440+ Plotly . purge ( gd ) ;
1441+ destroyGraphDiv ( ) ;
1442+ } ) ;
1443+
1444+ const mock = ( overrides = { } ) => {
1445+ return Lib . extendDeep (
1446+ {
1447+ data : [ { type : 'scattermap' , mode : 'markers' , lon : [ - 75 , - 74 , - 73 ] , lat : [ 40 , 41 , 42 ] } ] ,
1448+ layout : { width : 400 , height : 400 }
1449+ } ,
1450+ overrides
1451+ ) ;
1452+ } ;
1453+
1454+ it (
1455+ '@gl frames the data when no center/zoom set' ,
1456+ async ( ) => {
1457+ await Plotly . newPlot ( gd , mock ( ) ) ;
1458+ const { lng, lat } = gd . _fullLayout . map . _subplot . map . getCenter ( ) ;
1459+ expect ( lng ) . toBeCloseTo ( - 74 , 0 ) ;
1460+ expect ( lat ) . toBeCloseTo ( 41 , 0 ) ;
1461+ } ,
1462+ LONG_TIMEOUT_INTERVAL
1463+ ) ;
1464+
1465+ it (
1466+ '@gl refits when lon/lat change via restyle' ,
1467+ async ( ) => {
1468+ await Plotly . newPlot ( gd , mock ( ) ) ;
1469+ const z0 = gd . _fullLayout . map . zoom ;
1470+ await Plotly . restyle ( gd , { lon : [ [ - 75 ] ] , lat : [ [ 40 ] ] } , [ 0 ] ) ;
1471+ // Single-point trace → tighter zoom than the 3-point cluster
1472+ expect ( gd . _fullLayout . map . zoom ) . toBeGreaterThan ( z0 ) ;
1473+ } ,
1474+ LONG_TIMEOUT_INTERVAL
1475+ ) ;
1476+
1477+ it (
1478+ '@gl preserves center when only zoom is relayout-ed' ,
1479+ async ( ) => {
1480+ await Plotly . newPlot ( gd , mock ( ) ) ;
1481+ const { lon : origLon , lat : origLat } = gd . _fullLayout . map . center ;
1482+ await Plotly . relayout ( gd , { 'map.zoom' : 5 } ) ;
1483+ expect ( gd . _fullLayout . map . zoom ) . toBe ( 5 ) ;
1484+ expect ( gd . _fullLayout . map . center . lon ) . toBe ( origLon ) ;
1485+ expect ( gd . _fullLayout . map . center . lat ) . toBe ( origLat ) ;
1486+ } ,
1487+ LONG_TIMEOUT_INTERVAL
1488+ ) ;
1489+
1490+ it (
1491+ '@gl skips auto-fit when fitbounds is false' ,
1492+ async ( ) => {
1493+ await Plotly . newPlot ( gd , mock ( { layout : { map : { fitbounds : false } } } ) ) ;
1494+ expect ( gd . _fullLayout . map . center . lon ) . toBe ( 0 ) ;
1495+ expect ( gd . _fullLayout . map . center . lat ) . toBe ( 0 ) ;
1496+ expect ( gd . _fullLayout . map . zoom ) . toBe ( 1 ) ;
1497+ } ,
1498+ LONG_TIMEOUT_INTERVAL
1499+ ) ;
1500+
1501+ it (
1502+ '@gl skips refit after the user has changed center' ,
1503+ async ( ) => {
1504+ await Plotly . newPlot ( gd , mock ( ) ) ;
1505+ await Plotly . relayout ( gd , { 'map.center' : { lon : 0 , lat : 0 } } ) ;
1506+ await Plotly . restyle ( gd , { lon : [ [ - 75 ] ] , lat : [ [ 40 ] ] } , [ 0 ] ) ;
1507+ expect ( gd . _fullLayout . map . center . lon ) . toBe ( 0 ) ;
1508+ expect ( gd . _fullLayout . map . center . lat ) . toBe ( 0 ) ;
1509+ } ,
1510+ LONG_TIMEOUT_INTERVAL
1511+ ) ;
1512+
1513+ it (
1514+ '@gl refits after addTraces / deleteTraces' ,
1515+ async ( ) => {
1516+ await Plotly . newPlot ( gd , mock ( ) ) ;
1517+ const z0 = gd . _fullLayout . map . zoom ;
1518+ await Plotly . addTraces ( gd , { type : 'scattermap' , mode : 'markers' , lon : [ 140 ] , lat : [ - 30 ] } ) ;
1519+ // New trace pulls the fit far wider → lower zoom
1520+ expect ( gd . _fullLayout . map . zoom ) . toBeLessThan ( z0 ) ;
1521+ await Plotly . deleteTraces ( gd , 1 ) ;
1522+ // Back to the original 3-point fit
1523+ expect ( gd . _fullLayout . map . zoom ) . toBeCloseTo ( z0 , 5 ) ;
1524+ } ,
1525+ LONG_TIMEOUT_INTERVAL
1526+ ) ;
1527+
1528+ } ) ;
1529+
14331530describe ( 'map react' , function ( ) {
14341531 var gd ;
14351532
0 commit comments