Skip to content

Function properties in stubs should not render source code #975

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

Closed
kfischer-okarin opened this issue Sep 20, 2018 · 9 comments · Fixed by #1834
Closed

Function properties in stubs should not render source code #975

kfischer-okarin opened this issue Sep 20, 2018 · 9 comments · Fixed by #1834

Comments

@kfischer-okarin
Copy link

Version

1.0.0-beta.25

Reproduction link

https://codesandbox.io/s/135my5kk9j

Steps to reproduce

  1. Go to the Tests tabs and run the test
  2. Check the Console output in the Console tab

What is expected?

wrapper.html() should return something like

<childcomponent-stub clickhandler="[Function]"></childcomponent-stub> 

What is actually happening?

<childcomponent-stub clickhandler="function bound handleClick() {
    [native code]
}"></childcomponent-stub> 

I ran into the bug because the snapshot tests failed on our CI environment, even though I had properly updates the snapshots locally. The failing spot was a Function property which was rendered differently on local and CI environments (due to Istanbuls coverage comments being added).

@kfischer-okarin
Copy link
Author

Actually I'm not sure if this counts as a "bug" or rather a feature request...

@fbaeta
Copy link

fbaeta commented May 9, 2019

Here a workaround to ensure deterministic snapshots.

const HTML_ATTRS = /(\S+)\s*=\s*([']|["])\s*([\W\w]*?)\s*\2/gim;
const DEFAULT_OPTIONS = {
    functionRemplacement: '{[Function]}',
};

/**
 * Function is a predicate, to test attribute.
 * @callback AttrIgnoreFunction
 * @param {string} name The attribute name
 * @param {string} value The attribute name
 * @return {Boolean} Return `true` to ignore the element, `false` otherwise.
 */

/**
 * Serialize wrapper.
 *
 * `functionRemplacement` is used to ensure a deterministic snapshot (workaround of https://github.com/vuejs/vue-test-utils/issues/975)
 *
 * @param {Wrapper} wrapper
 * @param {Object} options
 * @param {string} options.functionRemplacement Default remplacement is '{[Function]}'.
 * @param {AttrIgnoreFunction} options.attrIgnore Default is `undefined`.
 *
 */
export function html(wrapper, options) {
    const opts = {
        ...DEFAULT_OPTIONS,
        ...options,
    };
    return wrapper.html().replace(HTML_ATTRS, (matches, name, quote, value) => {
        if (opts.functionRemplacement && /^\s*function\s*/gi.test(value)) {
            return `${name}="${opts.functionRemplacement}"`;
        }
        if (opts.attrIgnore && opts.attrIgnore(name, value)) {
            return '';
        }
        return matches;
    });
}

@ThomasRalee
Copy link

Is this issue on the roadmap?

@fallemand
Copy link

fallemand commented Jun 19, 2019

@briwa Can you reopen this issue? Since the PR that was going to fix it is closed.
Thanks!

@saptaru
Copy link

saptaru commented Sep 6, 2019

Do you have an estimate when it this going to be fixed?
Thanks!

@alexmccabe
Copy link

alexmccabe commented Oct 25, 2019

Here a workaround to ensure deterministic snapshots.

const HTML_ATTRS = /(\S+)\s*=\s*([']|["])\s*([\W\w]*?)\s*\2/gim;
const DEFAULT_OPTIONS = {
    functionRemplacement: '{[Function]}',
};

/**
 * Function is a predicate, to test attribute.
 * @callback AttrIgnoreFunction
 * @param {string} name The attribute name
 * @param {string} value The attribute name
 * @return {Boolean} Return `true` to ignore the element, `false` otherwise.
 */

/**
 * Serialize wrapper.
 *
 * `functionRemplacement` is used to ensure a deterministic snapshot (workaround of https://github.com/vuejs/vue-test-utils/issues/975)
 *
 * @param {Wrapper} wrapper
 * @param {Object} options
 * @param {string} options.functionRemplacement Default remplacement is '{[Function]}'.
 * @param {AttrIgnoreFunction} options.attrIgnore Default is `undefined`.
 *
 */
export function html(wrapper, options) {
    const opts = {
        ...DEFAULT_OPTIONS,
        ...options,
    };
    return wrapper.html().replace(HTML_ATTRS, (matches, name, quote, value) => {
        if (opts.functionRemplacement && /^\s*function\s*/gi.test(value)) {
            return `${name}="${opts.functionRemplacement}"`;
        }
        if (opts.attrIgnore && opts.attrIgnore(name, value)) {
            return '';
        }
        return matches;
    });
}

I couldn't get this to work, nothing changes. My error shows there are arrow functions, so I guess that's why.

Any ideas on when this will be fixed?

@visualjerk
Copy link

As a workaround, you can put /* istanbul ignore next */ before the function you pass to the prop.

So for your example it would be:

<template>
  <child-component :clickHandler="handleClick"/>
</template>


<script>
import ChildComponent from './ChildComponent';

export default {
  name: 'test-component',
  components: {
    ChildComponent,
  },
  methods: {
    /* istanbul ignore next */
    handleClick() {
      console.log('Click');
    },
  },
};
</script>

The downside is, that the function will not be included for the test coverage.

@alexmccabe
Copy link

My workaround is to just ignore the error in the coverage report and not to run coverage on the CI. It's not a perfect solution but it suffices.

@saptaru
Copy link

saptaru commented Aug 31, 2020

Any news about this fix?

The issue is occurring, in our case, while we are testing a component which doesn't pass a prop to the child component being defined as a Function type with default value in that specific child component as follows:
// prop in child component we need to test //... optionLabel: { type: Function, default(option) { return option[this.label]; } }, //...

The output of the jest coverage is the following:
optionlabel="function _default(option) { + /* istanbul ignore next */ + cov_lrcerpija.f[1]++; + cov_lrcerpija.s[7]++; return option[this.label]; }"

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants