6

I am new to Vue and followed the recommendation to use vue testing library. The only issue is I can't seem to find a way to inject my code into globalProperties in render function.

Does anyone know of an example where I can inject or mock it out?

main.js

app.config.globalProperties.$globals = globalMethods

...
const app = createApp(App)
app.config.globalProperties.$globals = globalMethods
app.config.globalProperties.$globalVars = globalVars

app.component("font-awesome-icon", fontawesome)

app.use(applicationStore);
app.use (Hotjar, hotjarConfig)
app.use(i18n)
app.use(router)

app.mount('#app')

From my vue component in create I am able to call

Component.vue

let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);

...  
  ,
  created() {
    let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
    this.myInputValue = formatedObj.formatedString;
    this.formatedCharacterCount = formatedObj.formatedCharacterCount;
    this.prevValue = this.myInputValue;
  },
...

tesst.spec.js

import { render } from '@testing-library/vue'
import FormatedNumericInput from '@/components/Component.vue'
import {globalMethods} from'@/config/global-methods'


const label = 'Price'
const initSettings = {
  props: {
    inputId: 'testInputId1',
    labelTxt: label
  }
};

beforeEach(() => {
});

test('a simple string that defines your test', () => {

  const { getByLabelText } = render(FormatedNumericInput, initSettings)
  const input = getByLabelText(label)
  
  // testing logic
  expect(input != null).toBe(true)
  expect(FormatedNumericInput != null).toBe(true)

})

** ERROR **

TypeError: Cannot read property 'maskValues' of undefined

      85 |   },
      86 |   created() {
    > 87 |     let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
         |                                     ^
      88 |     this.myInputValue = formatedObj.formatedString;
      89 |     this.formatedCharacterCount = formatedObj.formatedCharacterCount;
      90 |     this.prevValue = this.myInputValue;

      at Proxy.created (src/components/FormatedNumericInput.vue:87:37)
juliomalves
  • 42,130
  • 20
  • 150
  • 146
devtime
  • 83
  • 1
  • 4

2 Answers2

3

The second argument of render() is passed to @vue/test-utils mount(), so you could include the global.mocks mounting option to mock $globals.maskValues:

const { getByLabelText } = render(FormatedNumericInput, {
  ...initSettings,
  global: {
    mocks: {
      $globals: {
        maskValues: (inputValue, inputType) => {
          const formatedString = globalFormatValue(inputValue) // declared elsewhere
          return {
            formatedString,
            formatedCharacterCount: formatedString.length,
          }
        }
      }
    }
  }
})
tony19
  • 125,647
  • 18
  • 229
  • 307
1

This is my solution in actual Vue3/Vite/Vitest environment, I set some mocks globally, so I don't need to in every test suite.

// vitest.config.ts
import { mergeConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import viteConfig from './vite.config';

export default defineConfig(
    mergeConfig(viteConfig, { // extending app vite config
        test: {
            setupFiles: ['tests/unit.setup.ts'],
            environment: 'jsdom',
        }
    })
);
// tests/unit.setup.ts
import { config } from "@vue/test-utils"

config.global.mocks = {
  $t: tKey => tKey; // just return translation key
};

so for you it will be something like

config.global.mocks = {
    $globals: {
        maskValues: (inputValue, inputType) => {
          // ...implementation
          return {
            formatedString,
            formatedCharacterCount,
          }
        }
      }
   }
Luckylooke
  • 4,061
  • 4
  • 36
  • 49