Skip to content

Commit

Permalink
fix: vue2 global directives in component testing (#24488)
Browse files Browse the repository at this point in the history
* fix vue2 global directives in component testing

* fix vue2 global directives in component testing

* update test

* comment out flaky spec [skip ci]

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
Co-authored-by: Zachary Williams <ZachJW34@gmail.com>
  • Loading branch information
3 people committed Nov 14, 2022
1 parent cd23432 commit 741019d
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 4 deletions.
37 changes: 37 additions & 0 deletions npm/vue2/src/index.ts
Expand Up @@ -67,6 +67,17 @@ const installMixins = (Vue, options) => {
}
}

const registerGlobalDirectives = (Vue, options) => {
const directives =
Cypress._.get(options, 'extensions.directives')

if (Cypress._.isPlainObject(directives)) {
Object.keys(directives).forEach((name) => {
Vue.directive(name, directives[name])
})
}
}

const hasStore = ({ store }: { store: any }) => Boolean(store && store._vm)

const forEachValue = <T>(obj: Record<string, T>, fn: (value: T, key: string) => void) => {
Expand Down Expand Up @@ -125,6 +136,10 @@ type VueFilters = {
[key: string]: (value: string) => string
}

type VueDirectives = {
[key: string]: Function | Object
}

type VueMixin = unknown
type VueMixins = VueMixin | VueMixin[]

Expand Down Expand Up @@ -209,6 +224,27 @@ interface MountOptionsExtensions {
* @memberof MountOptionsExtensions
*/
plugins?: VuePlugins

/**
* Optional Vue directives to install while mounting the component
*
* @memberof MountOptionsExtensions
* @see https://github.com/cypress-io/cypress/tree/develop/npm/vue#examples
* @example
* const directives = {
* custom: {
* name: 'custom',
* bind (el, binding) {
* el.dataset['custom'] = binding.value
* },
* unbind (el) {
* el.removeAttribute('data-custom')
* },
* },
* }
* mount(Hello, { extensions: { directives }})
*/
directives?: VueDirectives
}

/**
Expand Down Expand Up @@ -382,6 +418,7 @@ export const mount = (
installFilters(localVue, options)
installMixins(localVue, options)
installPlugins(localVue, options, props)
registerGlobalDirectives(localVue, options)
registerGlobalComponents(localVue, options)

props.attachTo = componentNode
Expand Down
Expand Up @@ -4,7 +4,7 @@ type ProjectDirs = typeof fixtureDirs

const PROJECTS: {projectName: ProjectDirs[number], test: string}[] = [
{ projectName: 'angular-14', test: 'app.component' },
{ projectName: 'vueclivue2-configured', test: 'HelloWorld.cy' },
// TODO: Flaky. { projectName: 'vueclivue2-configured', test: 'HelloWorld.cy' },
{ projectName: 'react-vite-ts-configured', test: 'App.cy' },
{ projectName: 'react18', test: 'App.cy' },
{ projectName: 'create-react-app-configured', test: 'App.cy' },
Expand Down
2 changes: 1 addition & 1 deletion system-tests/projects/vueclivue2-configured/README.md
@@ -1,4 +1,4 @@
# vueclivue2-unconfigured
# vueclivue2-configured

## Project setup
```
Expand Down
@@ -0,0 +1,14 @@
<template>
<div class="child" v-custom="test" />
</template>

<script>
export default {
name: 'GlobalComponentWithCustomDirective',
data () {
return {
test: 'testing123'
}
}
}
</script>
@@ -1,5 +1,7 @@
import { mount } from 'cypress/vue2'
import HelloWorld from './HelloWorld.vue'
import GlobalComponentWithCustomDirective from './GlobalComponentWithCustomDirective.vue'
import custom from '../directive'

describe('<Logo />', () => {
it('contains the default slot in its h1', () => {
Expand All @@ -9,8 +11,43 @@ describe('<Logo />', () => {
propsData: {
msg: slotContent,
},
extensions: {
components: {
// stubbing for simplicity, this smoke test does not depend on
// GlobalComponent
GlobalComponentWithCustomDirective: {
render: h => h('div')
}
},
}
})

cy.contains('h1', slotContent)
})

it('Vue2 custom directive should work ', () => {
mount(GlobalComponentWithCustomDirective, {
extensions: {
directives: { custom },
},
})

cy.get('.child').should('have.attr', 'data-custom', 'testing123')
})

it('Vue2 custom directive should work in nested component', () => {
const slotContent = 'Welcome to testing in Vue CLI'

mount(HelloWorld, {
propsData: {
msg: slotContent,
},
extensions: {
components: { GlobalComponentWithCustomDirective },
directives: { custom },
},
})

cy.get('.child').should('have.attr', 'data-custom', 'testing123')
})
})
Expand Up @@ -25,6 +25,7 @@
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
<GlobalComponentWithCustomDirective/>
</div>
</template>

Expand Down
9 changes: 9 additions & 0 deletions system-tests/projects/vueclivue2-configured/src/directive.js
@@ -0,0 +1,9 @@
export default {
name: 'custom',
bind (el, binding) {
el.dataset['custom'] = binding.value
},
unbind (el) {
el.removeAttribute('data-custom')
},
}
8 changes: 7 additions & 1 deletion system-tests/projects/vueclivue2-configured/src/main.js
@@ -1,8 +1,14 @@
import Vue from 'vue'
import App from './App.vue'
import GlobalComponentWithCustomDirective from './components/GlobalComponentWithCustomDirective.vue'
import custom from './directive'

Vue.config.productionTip = false
Vue.component('GlobalComponentWithCustomDirective', GlobalComponentWithCustomDirective)
Vue.directive('custom', custom)

new Vue({
render: function (h) { return h(App) },
render (h) {
return h(App)
},
}).$mount('#app')
Expand Up @@ -3528,4 +3528,4 @@
],
"deferredHashFile": "yarn.lock",
"deferredHash": "ce60d1d6cc0c77f20dcfc741105a5c53593752f814bf3cab816a3024faf68bfc"
}
}

0 comments on commit 741019d

Please sign in to comment.