Allow ESM stubbing for functions in Vite
See original GitHub issueWhat would you like?
Utilizing Vite + Vue and Cypress Component Test Runner, how would you stub a composable function since you can’t stub the default export?
I can’t find a decent example that doesn’t utilize Babel, and the only solution we have come up with is exporting an object with methods that can be stubbed, which, to be honest, would be a large refactor.
When stubbing the default export, as shown below, an error is thrown: ESModules cannot be stubbed
. I know this is a valid error (here’s a great write-up for reference); however, we need the ability to stub the default exports of imported modules.
// Composable function
import { ref } from 'vue'
export default function useToggle (initialValue = false) {
const enabled = ref(initialValue)
return {
enabled
}
}
// Component usage
import useToggle from '../composables/useToggle'
....
setup(props) {
const { enabled } = useToggle(false)
onMounted(() => console.log(enabled.value)
}
// test.spec.ts
import { ref } from 'vue'
import useToggle from '../composables/useToggle'
// This doesn't work, and we're not using Babel since switching to Vite
// Throws an error: `ESModules cannot be stubbed`
cy.stub(useToggle, 'default').returns(
{
enabled: ref(true),
}
)
Why is this needed?
It’s a standard in Vue 3 to move stateful logic into composable functions. Composables typically export a default function (not an object) and devs need the ability to stub the outputs of a composable.
There is currently a workaround; however, it would require refactoring large blocks of code within our (and most) application whereby the composable exports a utility function that is used to set the returned values. This workaround (shown below) is a bit cumbersome and requires a very explicit, non-standard way of writing composable functions.
Here is the same composable provided above, rewritten for the workaround (not ideal):
// Composable function
import { ref, Ref } from 'vue'
export const getToggleData = {
enabled: (initialValue = false): Ref<boolean> => ref(initialValue)
}
export function useToggle(initialValue = false) {
const enabled = getToggleData.enabled(initialValue)
return {
enabled,
}
}
// Component usage
import useToggle from '../composables/useToggle'
....
setup(props) {
const { enabled } = useToggle(false)
onMounted(() => console.log(enabled))
}
// test.spec.ts
import { ref } from 'vue'
import { getToggleData } from '../composables/useToggle'
// This works, but isn't ideal due to the way the composable has to be written (not the norm)
cy.stub(getToggleData, 'enabled').returns(true)
Other
No response
Issue Analytics
- State:
- Created a year ago
- Comments:10 (5 by maintainers)
Top GitHub Comments
I’m interested in adding browser support to esmock. it would be awesome if someone would add a cypress test folder alongside esmock’s other test folders, and inside the test folder, add a passing test and a broken/failing test that uses esmock in the right place to try and browser-import a module with mock import tree.
👋 You want @baus or @ZachJW34 for Next-y or roadmap planning things.