How to mock nuxt build module in jest - jestjs

TLDR; Need help with mocking a nuxt build module in jest.
I declared a module in nuxt config like this to be globally accessible
// nuxt.config.ts
{
buildModules: [
'#nuxtjs/moduleA',
]
}
This build module is used by a component that is itself used everywhere throughout the app.
<script>
// TheComponent.vue
export default {
name: 'TheComponent',
computed: {
calculation() {
return this.moduleA.key === value
}
}
}
</script>
At the parent level
<template>
<div>
<!-- ... -->
<TheComponent :props="props" />
<!-- ... -->
</div>
</template>
I keep getting this error when running the tests:
[Vue warn]: Error in render: "TypeError: Cannot read property '<property>' of undefined"
What is the best way to declare the build module such that jest doesn't complain at the parent component level that moduleA doesn't exist?

Related

Vue test utils cannot find child component

I am running a Vue 3.0 with Quasar library. In the application there is a component that has a child component in it. With vue test utils v 2.2.6, I cannot seem to locate the child components in order to generate events. Why?
Simplified Parent Component
<template>
<q-dialog square persistent transition-show="scale" transition-hide="scale" >
<q-card-section class="q-px-xs q-pt-none">
<ChildComponent/>
</q-card-section>
</q-dialog>
</template>
<script setup>
//imports, props, etc
</script>
<style> ... </style>
Simplified Child Component
<template>
<q-card square bordered id="new-recipient-root-element" class="new-recipient">
<q-form>...</q-form>
</q-card>
</template>
<script setup>
//imports, props, etc
</script>
<style> ... </style>
Using Jest / vue test utils like so:
wrapper = mount(ParentComponent, {
props: { ...},
global: {
plugins: [i18n],
provide: {
store: ...
},
mocks: { ... }
}
});
wrapper.vm.show();
await nextTick();
domWrapper = new DOMWrapper(document.body);
...
await domWrapper.findComponent(ChildComponent).vm.$emit('myEvent');
domWrapper.findComponent(ChildComponent) always returns nothing. If I try domWrapper.findAllComponents(), it returns an empty array.
Also noticed that I can locate all the elements, but if I click on a button, no event seems to be generated since the handlers are not called and wrapper.emitted() contains nothing.
What am I missing?

Svelte: Disable ESLint Rule

I'm working on a Svelt project that uses ESlint, and I'm trying to disable a rule within my svelte template but can't find any information on how to do so. My code is the following:
<script lang="ts">
const unsubscribe = promiseWritable.subscribe((value) => {
promise = value;
});
onDestroy(unsubscribe);
</script>
{#if !!promise} <---- ESLint error here!
{#await promise then promiseResult}
<Info {promiseResult} />
{/await}
{/if}
This results in {#if !!promise} having the ESLint error:
Expected non-Promise value in a boolean conditional.eslint#typescript-eslint/no-misused-promises)
Regardless of whether I should disable this rule, I'm wondering how I would disable it within the file since adding either:
// eslint-disable-next-line... or <!-- eslint-disable-next-line... -->
above the line won't disable the error.
For Reference I am using https://github.com/sveltejs/eslint-plugin-svelte3
Since this commit, you can now add a "magic comment" to your Svelte file to disable individual validations using the form <!-- svelte-ignore rule-name -->.
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<div on:mouseover={mouseOver} on:mouseleave={mouseLeave} class="wrapper">
<slot name="content" />
</div>
The eslint-plugin-svelte plugin works fine with <!-- eslint-disable --> directives in svelte templates.
https://github.com/ota-meshi/eslint-plugin-svelte
I found a somewhat unsatisfying solution by adding /* eslint-disable */ to the bottom of the script tag giving us:
<script lang="ts">
const unsubscribe = promiseWritable.subscribe((value) => {
promise = value;
});
onDestroy(unsubscribe);
/* eslint-disable */
</script>
{#if !!promise} <---- No ESLint error anymore
{#await promise then promiseResult}
<Info {promiseResult} />
{/await}
{/if}
This will disable all linting in the HTML template.
You can set the settings.svelte3/named-blocks to true in your eslint config. Docs on svelte3/named-blocks. Then modify the targetted svelte files in overrides, and add template into ignorePatterns.
Such way requires no ...eslint-disable... in source files.
# .eslintrc.cjs
...
ignorePatterns: [
"**/*.svelte/*_template.ts",
],
overrides: [{ files: ["**/*.svelte/*.ts"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
"svelte3/named-blocks": true,
},
...
Related GitHub issue

Bind dynamic Vue image src from node_modules

I' am creating a Vue component that shows an SVG image from my node modules based on a given image name or key (given by an API).
If I put the source image directly like ~cryptocurrency-icons/svg/color/eur.svg, the resource loads.
But if I try to compute it with the props or by the mounted method asigning it using :src="imageSource" it does not load.
I'm new to Vue so I don't know why is this happening? Should I use images downloaded in a public directory instead of the NPM package?
<template lang="html">
<img src="~cryptocurrency-icons/svg/color/eur.svg" alt="icon" />
</template>
<script lang="js">
export default {
name: 'crypto-icon',
props: ['currency'],
mounted() {
this.imageSource = `~cryptocurrency-icons/svg/color/${this.currency}.svg`
},
data() {
return {
imageSource: ""
}
},
methods: {
getImageResource(){
return `~cryptocurrency-icons/svg/color/${this.currency}.svg`
}
},
computed: {
}
}
</script>
<style lang="scss" scoped>
.crypto-icon {}
</style>
You are missing the require attribute. Vue Loader, does this automatically when it compiles the <template> blocks in single file components. Try with this:
require(`~cryptocurrency-icons/svg/color/${this.currency}.svg`)
You can read more here.
I've solved it by using a Vue plugin (see vue-cryptoicons), although hatef is right about using require for image resources, using it in directories under node_modules tries to find the full path
~cryptocurrency-icons/svg/color in ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a7e19d86-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Wallet.vue?vue&type=template&id=7f1455a9&scoped=true&lang=html&
To install it, you can run: npm install --save ~cryptocurrency-icons/svg/color

[Vue warn]: Unknown custom element <navigation-drawer> - did you register the component correctly?

I imported two components from a custom library. When running "npm run serve" I don't get any errors in the cmd but when I open localhost it's a white screen and the console says
"[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> at src/App.vue
"
Here's App.vue:
<template>
<div id="app">
<navigation-drawer/>
<TFFooter/>
</div>
</template>
<script>
import NavigationDrawer from 'library'
import TFFooter from 'library'
export default {
name: 'App',
components: {
NavigationDrawer,
TFFooter
}
}
</script>
Try to change your component to NavigationDrawer to 'navigation-drawer':NavigationDrawer,

VueJS component throws warning if data has property that parent does not

I have a simple component handled by <script type="text/x-template"..., and it has its own data object that has only one property to control whether or not to show a div.
I am getting the following warning in Console:
[Vue warn]: Property or method "showDiv" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in root instance)
Live demo: https://jsbin.com/zucaqog/edit?html,js,output
Js:
Vue.component('my-comp', {
template: '#my-comp',
data: function() {
return { showDiv: false };
}
});
new Vue({
el: '#app',
data: {}
});
If I add showDiv: false to the parent's data object, I no longer receive the warning. But, I'd like to avoid doing that since this data property is relevant only to the local scope of the component. I have a feeling if I put the html of the component as a string in the template: ... then it might work, but, I'd rather have it inside of a script.
It's because you have your child component's template definition as a child of the #app div. The parent component is seeing that there is a reference to the showDiv variable inside of its template, so it's throwing the error.
Pull that x-template outside of the #app div:
<div id="app">
<my-comp></my-comp>
</div>
<script type="text/x-template" id="my-comp">
<div>
Value of showDiv is {{showDiv}}.
<button #click="showDiv=!showDiv">Toggle showDiv</button>
</div>
</script>

Resources