Suppress Vue warnings in unit tests - vue.js

I am trying to suppress my warnings in my tests following the config listed here: https://vue-test-utils.vuejs.org/api/config.html#silent, which is as follows:
import { config } from '#vue/test-utils';
// this should actually be the default but the default is not working
config.silent = true;
However, I am still seeing the warning in the test results:
TheQueue
✓ should show the queue bar if there are items queued
✓ should show the correct count of queued items in queued bar
[Vue warn]: Avoid mutating a prop directly since the value will be
overwritten whenever the parent component re-renders. Instead, use a
data or computed property based on the prop's value. Prop being
mutated: "mdTemplateData"
found in
---> <MdTab>
<MdContent>
<MdTabs>
<MdDrawer>
<TheQueue> at src/components/the-queue/TheQueue.vue
<Root>
It's worth noting that I do not see this error in normal usage of the app. This only pops up in tests (otherwise I would attempt to fix the actual suggested issue).
What am I doing wrong here and why can I not suppress these warning? Or am I misunderstanding what silent is supposed to do?

According to the VueJS docs - https://vue-test-utils.vuejs.org/api/config.html#silent
silent
type: Boolean
default: true
It suppresses warnings triggered by Vue while mutating component's
observables (e.g. props). When set to false, all warnings are visible
in the console. This is a configurable way which relies on
Vue.config.silent.
which relies on Vue.config.silent, so all you need is to import vue package and set it's config.silent to false
import Vue from `vue`
Vue.config.silent = true;
I put a working example here in my Github, it's just a fork of official example but it doesn't show warnings during the tests.
https://github.com/al1b/vue-test-utils-getting-started
For more information:
If you check the source code:
warn = (msg, vm) => {
const trace = vm ? generateComponentTrace(vm) : ''
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace)
} else if (hasConsole && (!config.silent)) {
console.error(`[Vue warn]: ${msg}${trace}`)
}
}

Related

How debug Vue3 applications with chrome and native javascript debugger

i started a new application with vue3 (created with vue-cli) and I'm not able to exploit native debugger in chrome
I have read that I had to specify the source map in my vue.config.js
module.exports = {
pluginOptions: {
quasar: {
importStrategy: 'kebab',
rtlSupport: false
}
},
configureWebpack: {
devtool: 'source-map'
},
transpileDependencies: [
'quasar'
]
}
But I'm still not able to explore my component code with a debugger
the result I have
screenshot not working
and what i want (screen from a vue2 project)
screenshot working
To use the native js debugger in a vue 2 application. You can do something like this:
methods: {
doSomething () {
this.loading = true
// doing something
debugger // native js debugger, in console check => this.loading (= true)
this.loading = false
}
}
Hopefully, it works the same way in vue 3.
You may be tempted to use it in the life-cycle hooks such as mounted, created ... but unfortunately, that never worked for me. Once the debugger halts the program, you can test it in the console by seeing what kind of object this identifies as.
When the native js debugger is used in a method enclosed by the methods option, it acts in a helpful and expected way. However, when it is used in a lifecycle hook like created the this object is not what you would expect it to be.
Additionals:
I actually stumbled on this question because I was looking for ways to use the native js debugger in the life cycle hooks. I'm hoping there might be vue 2 life-cycle hooks that support it.

Avoid app logic that relies on enumerating keys on a component instance

in my complex Vue project I am getting this console warning:
[Vue warn]: Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead.
Unfortunately I can not find the reason for this warning just by the above message.
How can I track down the reason for this warning?
Check if your watching an entire route object anywhere in your code. Doing so throws that error (in my case).
Refer this vue documentation on watching routes
Accessing router and current route inside setup
The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change.
Was able to fix this with the suggestion done by Glass Cannon.(https://stackoverflow.com/a/70205284/11787139)
To clarify and maybe help someone else: I was trying to send an Axios request to the server of which the data I sent through was composed of a direct component reference emitted by the component function.
Component
saveItem(){
this.saved = true;
setTimeout( this.resetState, 2500);
this.$emit('saveitem', this)
},
Parent
saveitem(e){
const data = {item : e}
axios.post(target, data, {headers . . .).then((response) => {}
})
The error disappeared when I instead fetched the index of the list item by doing so:
saveitem(e){
let item;
this.items.forEach( function(item, index, array) {
if(item.id == e.id) pointer = item
})
data.item = pointer
axios.post(target, data, {headers . . .).then((response) => {}
})
}
So I was also having this issue, but not for the reasons the accepted answer provided. It was occurring due to my Vuex store. After a lot of digging I discovered the cause was the presence of the "CreateLogger" plugin.
So if you're having this issue and it's not due to you watching an entire route, check if you're using the CreateLogger plugin in Vuex. That might be the culprit.
This happens for me when I pass this to a data object
data() {
return {
updateController: new UpdateController({
reportTo: this
})
}
}
This used to work fine with Vue 2 but causes this error in Vue 3.
Making this modification solved the problem for me.
data() {
return {
updateController: new UpdateController({
reportTo: () => this
})
}
}
I know this might be anti-pattern but I needed to inject partial reactivity to a non-reactive part of a JS library and this was the most not complicated way of achieving this that I can think of.
This happens to me when destructuring a ref without .value.
This was happening to me only in Firefox, and when I removed the Vue Dev Tools extension it stopped. After re-installing Vue dev tools it hasn't come back. Make sure you have the latest version of the Vue Dev Tools for your browser.

TypeError: Converting circular structure to JSON with StorybookJS on React Native

This happens whenever I navigate to a new Story within the Storybook Navigator. Thanks!
ExceptionsManager.js:126 Unhandled JS Exception: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'HooksContext'
| property 'currentContext' -> object with constructor 'Object'
--- property 'hooks' closes the circle
I'm using React Native 0.61.5 and #storybook/react-native 5.3.9
I'm dealing with the same issue and unfortunately don't have enough experience with Storybook or React Native to diagnose.
However, I was able to patch the module as described in https://github.com/storybookjs/storybook/issues/9294, i.e. "hooks.currentContext = Object.assign({}, context, { hooks: null });"
To reiterate, this is not a perfect solution, as the original bug comes from the nested, circular relationship between currentContext and hooks. This simply sets hooks to null to terminate the circular structure.
In my case, setting onDeviceUI to false solves this issue when I use storybook web UI.
storybook/index
const StorybookUIRoot = getStorybookUI({
asyncStorage: require('#react-native-community/async-storage').AsyncStorage,
onDeviceUI: false,
shouldPersistSelection: true,
shouldDisableKeyboardAvoidingView: true,
// isUIHidden: true,
})

Vue JS How to catch errors globally and display them in a top level component

I have set up Vue so that I have a top level AppLayout component which just includes a Navigation Menu component, the router-view and, which uses v-if to optionally display an ErrorDisplay component if the error data item is set. I set this from an err state variable in the Vuex store.
That is where I want to get to. However, I think the problem is more fundamental.
In a lower component, I have a submit function that gets called when I click the submit button. To test error handling I have put
throw new Error('Cannot Submit');
In my Main.js I have
handlers for window.orerror, window.addEventListner, Vue.config.errorhandler, Vue.config.warnhandler
All of these should just call the errHandler function, which just calls an action to update the err variable in the state. The hope being that this will then result in the ErrorDisplay component showing on my top level component.
However, I have console.log statements as the first statement in all the above handlers and in my errHandler function. None of these console.logs are getting executed.
In the Console in Chrome, I am just seeing
[vue warn]: Error in v-on handler: "Error: Cannot Submit"
So it is getting the text from my throw, but none of the error handlers seem to be capturing this?
Vue provides Global configuration config.errorHandler to capture error inside Vue components Globally.
As per Official Docs
Assign a handler for uncaught errors during component to render function and watchers. The handler gets called with the error and the Vue instance.
This is how it can be used:
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` is a Vue-specific error info, e.g. which lifecycle hook
// the error was found in. Only available in 2.2.0+
}
Official docs
Hope this helps!
Did more research and I think someone may have already raised a bug report with Vue for this
PR on Vue
https://github.com/vuejs/vue/pull/5709
So it looks like the problem is that the way that I am trying to test this isn't being caught.

Instance Vue if element exists?

I'm building an app that a page has some vms, in others not. When we change from one page to another show the following warning:
[Vue warn]: Cannot find element: #element-id
How do I instantiate VMs only if there is the element on the page and avoid the error?
NOTE: I'm using Rails asset pipeline, so, all the javascript is concatenated into a single file.
There are no issues just leaving it as is. This is just a warning that only runs when debug mode is on, so you should have it turned off in production anyway.
If you want to get rid of it, just check if the element exists before launching Vue -
if(document.getElementById("element-id")){
new Vue({...})
}
Ref: How to check if element exists in the visible DOM?
This is a bit of an old question. I found this Vue example being useful
https://v2.vuejs.org/v2/api/#Vue-extend
So you can create a Vue class and initiate it only if the dom element is present in the DOM.
// create constructor
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// create an instance of Profile and mount it on an element
if(document.getElementById("element-id")){
new Profile().$mount('#element-id')
}