Home  >  Q&A  >  body text

Why do I get "TypeError: cannot convert symbol value to string" when I try to create a clone of a Vuex store in a Jest unit test?

<p>I have a working Vue 2.6 / Vuex 3.6 / TypeScript application. I want to add some unit tests before doing some complex refactoring. Once I had Jest and Vue Test Utils installed and configured, I tried following the instructions provided in the official Vue Test Utils guide. </p> <p>Adapt the instructions to my specific project, like this: </p> <pre class="brush:js;toolbar:false;">import { createLocalVue } from '@vue/test-utils' import Vuex from 'vue' import store from 'store' import { cloneDeep } from 'lodash' test("SET_CURRENT_VTK_INDEX_SLICES should update the VTK index slices", () => { const localVue = createLocalVue() localVue.use(Vuex) const store = new Vuex.Store(cloneDeep(storeConfig)) expect(store.state.iIndexSlice).toBe(0) store.commit('SET_CURRENT_VTK_INDEX_SLICES', { indexAxis: 'i', value: 1 }) }) </pre> <p>But when I execute <code>npm run test:unit</code> I get the following error: </p> <blockquote> <p>"TypeError: cannot convert symbol value to string"</p> </blockquote> <p>I don't think there are any symbols in the store, but use a recursive function to check the store and all its children. (I stole this code from somewhere I don't remember): </p> <pre class="brush:js;toolbar:false;">function findSymbolInStore(store) { for (const key in store) { console.log(key); if (store.hasOwnProperty(key)) { const value = store[key]; if (typeof value === 'object') { if (value instanceof Symbol) { console.log(`Symbol found: ${key}`); } else { findSymbolInStore(value); } } } } } findSymbolInStore(store.state); </pre> <p>No symbols found in the store.</p> <p>I hit a few more dead ends and tried stringifying the store to see where the symbols were: </p> <pre class="brush:js;toolbar:false;">try { const thisStore = JSON.stringify(store); } catch (err) { console.error('Error converting object to string;', err); } </pre> <p>But this throws the error: </p> <blockquote> <p>Type error: converting loop structure to JSON</p> </blockquote> <p>Then try stringifying with <code>flatted</code>: </p> <pre class="brush:js;toolbar:false;">import flatted from 'flatted'; const stringifyStore = flatted.stringify(store); const parsedStore = flatted.parse(stringifyStore); </pre> <p>This seemed to get me a step further and now I'm getting the error: </p> <blockquote> <p>TypeError: Cannot read property of undefined (read 'iIndexSlice')</p> </blockquote> <p>This is strange because I can see that <code>iIndexStore</code> has a default value of 0 in the store. Thankfully, at this point Amit Patel got me on the right track by pointing out that not only <code>iIndexSlice</code> was undefined, but the entire <code>store.state</code> was also undefined. </p> <p>I stumbled upon a [Vuex GitHub issue][4] with a similar error to the one I encountered: </p> <blockquote> <p>[vuex] getters should be functions, but 'getters.currentView' is {}</p> </blockquote> <p>In the question referenced above, the author recommends not exporting the store, but only the store's configuration. I realized that the app's store was exporting an actual store instance. The Vuex storage definition looks like this: </p> <pre class="brush:js;toolbar:false;">const store = new Vuex.Store({ state: { iIndexSlice: 0, // ... }, getters: { currentView(state) { // Function code ... } mutations: { // code }, actions: { // code } }); export default store; </pre> <p>But what now? </p> <p>HT: To Mujeeb, who helped me with some symbolic debugging. </p> <p> NOTE: I could have skipped the dead ends etc, but I thought others might have the same difficulty and it might be easier to google the answer if some bugs etc were mentioned. </p>
P粉604848588P粉604848588443 days ago500

reply all(1)I'll reply

  • P粉421119778

    P粉4211197782023-08-27 12:14:33

    (Welcome to another episode of "Dave spent way too much time fixing this...it's very trivial, but hopefully saves another person who will make the same mistake":

    I refactored the Vuex store as follows:

    export const storeConfig = {
     state: {
      iIndexSlice: 0,
      // ...
     },
     getters: {
      currentView(state) {
       // Function code ...
      }
     mutations: {
      // code
     },
     actions: {
      // code
     }
    };
    
    const store = new Vuex.Store(storeConfig);
    
    export default store;
    

    Then I just need to make a small adjustment to the Jest test:

    // import store from './store'
    // to:
    import { storeConfig } from './store'
    })
    

    Now the test runs without problems.

    reply
    0
  • Cancelreply