首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TypeError:_mapboxGl.default.Map不是构造函数

TypeError:_mapboxGl.default.Map不是构造函数
EN

Stack Overflow用户
提问于 2019-12-31 10:28:46
回答 2查看 2.6K关注 0票数 6

试图为react.js组件编写单元测试。该组件实现了使用mapbox呈现的映射。但不幸的是,我遇到了一系列问题:

第一个是: TypeError: window.URL.createObjectURL不是一个函数

我通过添加以下代码解决了这个问题:https://github.com/mapbox/mapbox-gl-js/issues/3436

代码语言:javascript
运行
复制
jest.mock('mapbox-gl/dist/mapbox-gl', () => ({
    Map: () => ({})
}))

,然后第一个是: ReferenceError:浅层不是定义的

为了在此基础上解决这个问题:ReferenceError on enzyme import

1) npm istall酶,

2)增加一行:

代码语言:javascript
运行
复制
import { shallow, render, mount } from 'enzyme'

第三个问题是:从‘酶适配器-反应-15’导入适配器。

由于本文:Could not find declaration file for enzyme-adapter-react-16?,下一步是添加以下代码:

代码语言:javascript
运行
复制
import Adapter from 'enzyme-adapter-react-16'
import enzyme from 'enzyme'

enzyme.configure({ adapter: new Adapter() })

,现在终于有了一个拥有: TypeError:_mapboxGl.default.Map不是构造函数

现在,不幸的是,我在网上找不到有意义的解决方案。

有人有类似的问题吗?

为什么单元测试mapbox如此困难?

也许我做错了,而整个解决方案是垃圾?如果是的话,有谁能提出替代方案呢?

以下是整个测试代码:

代码语言:javascript
运行
复制
import React, { Component } from 'react'
import { shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import enzyme from 'enzyme'

enzyme.configure({ adapter: new Adapter() })

import Map from '../Map'

jest.mock('mapbox-gl/dist/mapbox-gl', () => ({
    Map: () => ({})
}))

describe('<Map />', ()=>{

    let mapWrapper
    let mapInstance

    const map = (disableLifecycleMethods = false)=>shallow(<Map />,{disableLifecycleMethods})

    beforeEach(()=>{
        mapWrapper = map()
        mapInstance = mapWrapper.instance()
    })

    afterEach(() => {
        mapWrapper = undefined;
        mapInstance = undefined;
    })

    it('renders without crashing', () => {
        expect(map().exists()).toBe(true);
    })
})

以下是经过测试的组件代码:

代码语言:javascript
运行
复制
import React, { Component } from 'react'
import mapboxgl from 'mapbox-gl'

//Mechanics
import {importContours} from './utilities/importContours'
import {addData} from './utilities/addData'
import {setLegend} from './utilities/setLegend'

//Components
import Searchbar from '../search/Searchbar'
import Tabbar from '../tabbar/Tabbar'
import Legend from '../legend/Legend'
//import Popup from '../popup/Popup'

class Map extends Component {

    map

    constructor(){
        super()
        this.state = {
            active: null,
            fetchData: null,
            mapType: 0,
            searchedPhrase: ''
        }
    }

    componentDidUpdate() {
        this.setMapLayer()          
    }

    componentDidMount() {

        mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_TOKEN
        this.map = new mapboxgl.Map({
            container: 'Map',
            style: 'mapbox://styles/mapbox/streets-v9',
            center: [16.145136, 51.919437],
            maxZoom: 13,
            minZoom: 3,
            zoom: 5.7,
        })

        this.map.once('load', () => {}) 
    }

    setMapLayer(){

        if (!this.map.loaded() || this.state.searchedPhrase === '') return

        var contours = importContours(this.state.mapType)
        var contoursWithData = addData(contours, this.state.mapType, this.state.searchedPhrase)
        contoursWithData.then((data)=>{
            var mpSource = this.map.getSource("contours")

            if (typeof mpSource === 'undefined') 
                this.map.addSource('contours', { type: 'geojson', data })
            else 
                this.map.getSource("contours").setData(data)

            var mpLayer = this.map.getLayer("contours")

            if (typeof mpLayer === 'undefined') {
                this.map.addLayer({
                    id: 'contours',
                    type: 'fill',
                    source: 'contours',
                    layout: {},
                    paint: {
                        'fill-opacity': [
                            'case',
                            ['boolean', ['feature-state', 'hover'], false],
                            0.8,
                            0.4
                        ]
                    }
                }, 'country-label-lg')

                this.map.addLayer({
                    id: 'state-borders',
                    type: 'line',
                    source: 'contours',
                    layout: {},
                    paint: {
                        'line-color': '#c44cc0',
                        'line-width': 0.01
                    }
                })
            }

            var hoveredStateId = null

            // When the user moves their mouse over the state-fill layer, we'll update the
            // feature state for the feature under the mouse.
            this.map.on('mousemove', 'contours', (e) => {
                if (e.features.length > 0) {
                    if (hoveredStateId) {
                        this.map.setFeatureState(
                            { source: 'contours', id: hoveredStateId },
                            { hover: false }
                        )
                    }

                    hoveredStateId = e.features[0].id
                    this.map.setFeatureState(
                        { source: 'contours', id: hoveredStateId },
                        { hover: true }
                    )
                }
            })

            // When the mouse leaves the state-fill layer, update the feature state of the
            // previously hovered feature.
            this.map.on('mouseleave', 'contours', () => {
                if (hoveredStateId) {
                    this.map.setFeatureState(
                        { source: 'contours', id: hoveredStateId },
                        { hover: false }
                    )
                }
                hoveredStateId = null
            }) 

            // When the user click their mouse over the layer, we'll update the
            this.map.on('click', 'contours', (e) => {

                var popupHTML = `<Popover 
                    style = { zIndex: 2, position: 'absolute' }
                    anchorOrigin={{ vertical: 'center',horizontal: 'center'}}
                    transformOrigin={{vertical: 'center',horizontal: 'center'}}
                >
                    ${e.features[0].id}
                </Popover>`

                if (e.features.length > 0) {
                    new mapboxgl.Popup(
                        {style:"zIndex: 2"},
                        {closeButton: false, closeOnClick: true}
                        )
                    .setLngLat(e.lngLat)
                    .setHTML(popupHTML)
                    .addTo(this.map);
                }
            })

            this.setState({
                active: setLegend(data)
            })

            //Set fill
            if(this.state.active == null) return 

            const { property, stops } = this.state.active

            this.map.setPaintProperty('contours', 'fill-color', {
              property,
              stops
            })
        })
    }

    handleChange = (newMapType) => {

        if (this.state.mapType === newMapType) return

        const { searchedPhrase } = this.state

        if (typeof searchedPhrase === 'undefined')return

        this.setState({mapType:newMapType})
    }

    handleSearch = (newSearchPhrase) => {

        if (typeof newSearchPhrase === 'undefined') return

        this.setState({searchedPhrase:newSearchPhrase.toUpperCase()})    
    }

    render(){
        return (
            <div id="Map">
                <Searchbar click={this.handleSearch.bind(this)}/>
                <Tabbar click={this.handleChange.bind(this)}/>
                <Legend active={this.state.active}/>
            </div>
        )
    }
}

export default Map
EN

Stack Overflow用户

发布于 2020-12-26 15:48:40

由于莫罗的回答,我成功地在我的测试文件中直接修复了:

代码语言:javascript
运行
复制
import Map from '@/components/modules/Home/Map/Map'

jest.mock('mapbox-gl/dist/mapbox-gl', () => ({
  Map: jest.fn(),
  Marker: jest.fn().mockReturnValue({
    setLngLat: jest.fn().mockReturnValue({
      setPopup: jest.fn().mockReturnValue({
        addTo: jest.fn().mockReturnValue({})
      })
    })
  }),
  Popup: jest.fn().mockReturnValue({
    setHTML: jest.fn().mockReturnValue({ on: jest.fn() })
  })
}))

describe('Map', () => {
  it('should match snapshot', () => {
    // When
    const wrapper = shallowMount(Map)

    // Then
    expect(wrapper).toMatchSnapshot()
  })
})
票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59542854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档