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粉604848588
P粉604848588 2023-08-26 16:06:50
0
1
534
<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粉604848588
P粉604848588

reply all(1)
P粉421119778

(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.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template