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

Vue 3 defineProps and defineEmits having issues #3305

Open
justgrumpy opened this issue Dec 8, 2021 · 6 comments
Open

Vue 3 defineProps and defineEmits having issues #3305

justgrumpy opened this issue Dec 8, 2021 · 6 comments
Labels
🐛 Bug Something isn't working ☠ stale Marked as stale by the stale bot, will be removed after a certain time.

Comments

@justgrumpy
Copy link

Summary

I am having issues using Stryker with the Vue 3 <script setup> for Composition API inside Single File Components (SFCs). Specifically I am having issues with defineProps and defineEmits, https://v3.vuejs.org/api/sfc-script-setup.html#defineprops-and-defineemits. I get an error like the following:

13:38:55 (13792) ERROR DryRunExecutor One or more tests resulted in an error:
        undefined[@vue/compiler-sfc] `defineProps()` in <script setup> cannot reference locally declared variables because it 
will be hoisted outside of the setup() function. If your component options require initialization in the module scope, use a separate normal <script> to export the options instead.

C:\dev\my-vue-app\stryker-tmp\sandbox309818\src\components\HelloWorld.vue
65 |
66 |  import { ref } from 'vue';
67 |  defineProps(stryMutAct_9fa48("0") ? {} : (stryCov_9fa48("0"), {
   |              ^^^^^^^^^^^^^^^^
68 |    msg: String
69 |  })); Error: [@vue/compiler-sfc] `defineProps()` in <script setup> cannot reference locally declared variables because it will be hoisted outside of the setup() function. If your component options require initialization in the module scope, use a 
separate normal <script> to export the options instead.

The app works normally and the Jest tests run fine. I assume that Stryker in mutating is doing something to reference locally declared variables causing this error???

A full sample application with the problem can be found here, https://github.com/justgrumpy/my-vue-app.

Stryker config

{
    "$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
    "mutator": {
        "plugins": []
    },
    "tempDirName_comment": "Jest doesn't play nice with the default (.stryker-tmp).",
    "tempDirName": "stryker-tmp",
    "testRunner": "jest",
    "coverageAnalysis": "off"
}

Test runner config

Stryker environment

+-- @stryker-mutator/core@5.5.1
+-- @stryker-mutator/jest-runner@5.5.1
+-- @stryker-mutator/jest-runner@5.5.1
+-- @vue/vue3-jest@27.0.0-alpha.4
+-- babel-jest@27.4.2
+--  jest@27.4.3

Test runner environment

jest

babel.config.js

module.exports = {
  presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
};

jest.config.js

const {defaults} = require('jest-config');
module.exports = {
  moduleFileExtensions: [...defaults.moduleFileExtensions, 'vue'],
  transform: {
    '^.+\\.js$': 'babel-jest',
    '^.+\\.vue$': '@vue/vue3-jest',
  },
  testEnvironment: 'jsdom',
};

Your Environment

software version(s)
node v16.13.0
npm 8.1.0
Operating System

Add stryker.log

stryker.log

@justgrumpy justgrumpy added the 🐛 Bug Something isn't working label Dec 8, 2021
@nicojs
Copy link
Member

nicojs commented Dec 9, 2021

Hi @justgrumpy thanks for opening this issue.

I assume that Stryker in mutating is doing something to reference locally declared variables causing this error???

Yes, it does. You can see it in your error message:

67 |  defineProps(stryMutAct_9fa48("0") ? {} : (stryCov_9fa48("0"), {
   |              ^^^^^^^^^^^^^^^^
68 |    msg: String

The variable stryMutAct_9fa48 is inserted in the top of the <script> tag. You can also see that for yourself inside the stryker-tmp sandbox directory after a failing run.

The problem seems to be that defineProps and defineEmits are compiler macros instead of JavaScript functions.

The only good solution (I can think of) for these kinds of problems is a feature called "ignore-plugins" described in #3229. We could create a specific vue-ignore-plugin that automatically ignores compiler macros.

As a workaround, you can insert a stryker disable comment

<script setup>
import { ref } from 'vue'

+// Stryker disable next-line all: Don't mutate compiler macros
defineProps({
  msg: String
})

const count = ref(0)
</script>

Does that work for you?

@justgrumpy
Copy link
Author

This does work for me. I was unaware of the ability to disable Stryker for a specific line of code. This appears to be a feature added with 5.4?

An ignore-plugin would also be very convenient to eliminate so many comments. If there are several components, comments will be needed in each .vue file. If more than one property is defined and object-based syntax is used to define the property (https://v3.vuejs.org/api/options-data.html#props), several comments are required in the same file...

// Stryker disable next-line all: Don't mutate compiler macros
defineProps({
  // Stryker disable next-line all: Don't mutate compiler macros
  msg: { type: String, required: true },
  // Stryker disable next-line all: Don't mutate compiler macros
  anotherProp: { type: String, required: false }
})

@nicojs
Copy link
Member

nicojs commented Dec 9, 2021

Yes, it was added in 5.4. We're rapidly evolving currently, focusing on user experience and performance. Following @stryker_mutator on Twitter helps with keeping up to date. Our release notes should also be quite readable. About once a year, we also write a blog article with some bigger changes here: https://stryker-mutator.io/blog

I'm first focussing on improving support for native ESM (see #2922), after that I want to focus on ignore plugins. Let's keep this issue open as a reminder.

You can actually improve your use case a lot using this:

// Stryker disable all: Don't mutate compiler macros
defineProps({
  msg: { type: String, required: true },
  anotherProp: { type: String, required: false }
})
// Stryker restore all

See https://stryker-mutator.io/docs/stryker-js/disable-mutants/#using-a--stryker-disable-comment for the docs

@stale
Copy link

stale bot commented Dec 11, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the ☠ stale Marked as stale by the stale bot, will be removed after a certain time. label Dec 11, 2022
@nicojs
Copy link
Member

nicojs commented Dec 12, 2022

Thanks, but we want to keep this open. We shouldn't ignore the ignore plugin use case

@stale stale bot removed the ☠ stale Marked as stale by the stale bot, will be removed after a certain time. label Dec 12, 2022
Copy link

stale bot commented Dec 15, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the ☠ stale Marked as stale by the stale bot, will be removed after a certain time. label Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 Bug Something isn't working ☠ stale Marked as stale by the stale bot, will be removed after a certain time.
Projects
None yet
Development

No branches or pull requests

2 participants