Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exceptions handled in custom errorHandler are logged to console.error #1760

Closed
marcgibbons opened this issue Jan 6, 2021 · 0 comments · Fixed by #1761, eddieferrer/sizesquirrel-open#212 or nextcloud/social#1222
Labels

Comments

@marcgibbons
Copy link
Contributor

marcgibbons commented Jan 6, 2021

Subject of the issue

Exceptions that are caught and handled in an errorHandler are re-thrown and logged to console.error.

instancedErrorHandlers.forEach(instancedErrorHandler => {
instancedErrorHandler(error, vm, info)
})
throw error

Steps to reproduce

  • Define an errorHandler which suppresses a specific error type. The intended use case is to trigger some global side-effect whenever this type of exception is raised.
  • Write a test which triggers this exception via an event handler
// error.test.js

import { createLocalVue, mount } from '@vue/test-utils';
import Vue from 'vue';

class MyCustomError extends Error {};

const MyComponent = Vue.component('MyComponent', {
  template: '<button id="btn" @click="clickHandler">Click me</button>',

  methods: {
    clickHandler() {
      throw new MyCustomError();
    }
  }
});


const errorHandler = (err, vm, info) => {
  if (err instanceof MyCustomError) {
    // TODO: Some side-effect like vm.$router.push, vm.$store.dispatch
    return;
  }
  throw err // Raise others
}

describe('custom error handler', () => {
  test('clicking the button does not raise MyCustomError', () => {
    const localVue = createLocalVue({ errorHandler });
    const wrapper = mount(MyComponent, { localVue });
    wrapper.trigger('click');
  });
});

Expected behaviour

  • The test should pass
  • There should be no console.error

Actual behaviour

  • The test passes
  • The caught exception is thrown and then logged to console
Output:
 PASS  ./error.test.js
  custom error handler
    ✓ clicking the button does not raise MyCustomError (53 ms)

  console.error
    [Vue warn]: Error in v-on handler: "Error"

    found in

    ---> <MyComponent>
           <Root>

      at warn (node_modules/vue/dist/vue.runtime.common.dev.js:621:15)
      at logError (node_modules/vue/dist/vue.runtime.common.dev.js:1880:5)
      at globalHandleError (node_modules/vue/dist/vue.runtime.common.dev.js:1875:3)
      at handleError (node_modules/vue/dist/vue.runtime.common.dev.js:1835:5)
      at invokeWithErrorHandling (node_modules/vue/dist/vue.runtime.common.dev.js:1858:5)
      at HTMLButtonElement.invoker (node_modules/vue/dist/vue.runtime.common.dev.js:2175:14)
      at HTMLButtonElement.original._wrapper (node_modules/vue/dist/vue.runtime.common.dev.js:6895:25)

  console.error
    MyCustomError:
....

Possible Solution

Update the behaviour of vue-test-utils to match Vue's.

VueJS will log errors to console if:

  • No errorHandler is defined; or
  • An error was raised from within a custom errorHandler

Errors will not be logged if a defined errorHandler returns without throwing an exception.

https://github.com/vuejs/vue/blob/b51430f598b354ed60851bb62885539bd25de3d8/src/core/util/error.js#L58-L71

function globalHandleError (err, vm, info) {
  if (config.errorHandler) {
    try {
      return config.errorHandler.call(null, err, vm, info)
    } catch (e) {
      // if the user intentionally throws the original error in the handler,
      // do not log it twice
      if (e !== err) {
        logError(e, null, 'config.errorHandler')
      }
    }
  }
  logError(err, vm, info)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment