Skip to content
This repository was archived by the owner on Dec 12, 2020. It is now read-only.

Commit ac778f3

Browse files
authored
feat: rest render function components (#343)
``` <app-component :elementtype = "'div,blue,30,div1'">Hello World</app-component> ``` for individual component to be mounted ```js mount(appComponent, { propsData: { elementtype: 'h3,red,30,h3tag', }, }) ```
1 parent e0fa815 commit ac778f3

File tree

5 files changed

+206
-0
lines changed

5 files changed

+206
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ Spec | Description
597597
Spec | Description
598598
--- | ---
599599
[mocking-imports](cypress/component/advanced/mocking-imports) | Stub ES6 imports from the tests
600+
[render-functions](cypress/component/advanced/render-functions) | Mounting components with a [render function](https://www.tutorialandexample.com/vue-js-render-functions/)
600601
<!-- prettier-ignore-end -->
601602

602603
### Full examples
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# render functions
2+
3+
Based on examples from [Vue.js Render Functions](https://www.tutorialandexample.com/vue-js-render-functions/) tutorial.
4+
5+
See [spec.js](spec.js) for examples of mounting a component, using multiple components, passing props data.
6+
7+
![Components](./images/colors.png)
Loading
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/// <reference types="cypress" />
2+
import { mount } from 'cypress-vue-unit-test'
3+
4+
describe('Single render function component', () => {
5+
// the component definition
6+
const appComponent = {
7+
template: '<h1>hi! This is a Render Function Example</h1>',
8+
data() {
9+
return {}
10+
},
11+
}
12+
13+
const mountOptions = {
14+
// we want to use custom app component above
15+
extensions: {
16+
components: {
17+
'app-component': appComponent,
18+
},
19+
},
20+
}
21+
22+
it('loads', () => {
23+
mount(
24+
{
25+
template: `
26+
<div>
27+
<app-component></app-component>
28+
</div>
29+
`,
30+
},
31+
mountOptions,
32+
)
33+
cy.contains('h1', 'hi!')
34+
})
35+
36+
it('loads 3 times', () => {
37+
// tip: always have top level single root element
38+
mount(
39+
{
40+
template: `
41+
<div>
42+
<app-component></app-component>
43+
<app-component></app-component>
44+
<app-component>foo</app-component>
45+
</div>
46+
`,
47+
},
48+
mountOptions,
49+
)
50+
cy.get('h1')
51+
.should('have.length', 3)
52+
.each(($el) => {
53+
expect($el).to.contain('hi!')
54+
})
55+
})
56+
})
57+
58+
describe('Component with slot', () => {
59+
// the component definition
60+
const appComponent = {
61+
template: '<h1><slot></slot></h1>',
62+
data() {
63+
return {}
64+
},
65+
}
66+
67+
const mountOptions = {
68+
// we want to use custom app component above
69+
extensions: {
70+
components: {
71+
'app-component': appComponent,
72+
},
73+
},
74+
}
75+
76+
it('loads', () => {
77+
mount(
78+
{
79+
template: `
80+
<div>
81+
<app-component>Hello</app-component>
82+
</div>
83+
`,
84+
},
85+
mountOptions,
86+
)
87+
cy.contains('h1', 'Hello')
88+
})
89+
90+
it('loads 3 different components', () => {
91+
// tip: always have top level single root element
92+
mount(
93+
{
94+
template: `
95+
<div>
96+
<app-component>Hello World</app-component>
97+
<app-component>Hello John</app-component>
98+
<app-component>Hello Peter</app-component>
99+
</div>
100+
`,
101+
},
102+
mountOptions,
103+
)
104+
cy.get('h1')
105+
.should('have.length', 3)
106+
.and(($el) => {
107+
expect($el[0]).to.have.text('Hello World')
108+
expect($el[1]).to.have.text('Hello John')
109+
expect($el[2]).to.have.text('Hello Peter')
110+
})
111+
})
112+
})
113+
114+
describe('Component with arguments', () => {
115+
// the component definition
116+
const appComponent = {
117+
render: function (createElement) {
118+
var a = this.elementtype.split(',')
119+
return createElement(
120+
a[0],
121+
{
122+
attrs: {
123+
id: a[3],
124+
style: 'color:' + a[1] + ';font-size:' + a[2] + ';',
125+
},
126+
},
127+
this.$slots.default || '<EMPTY>',
128+
)
129+
},
130+
props: {
131+
elementtype: {
132+
attributes: String,
133+
required: true,
134+
},
135+
},
136+
}
137+
138+
const mountOptions = {
139+
// we want to use custom app component above
140+
extensions: {
141+
components: {
142+
'app-component': appComponent,
143+
},
144+
},
145+
}
146+
147+
it('renders different colors', () => {
148+
// tip: always have top level single root element
149+
mount(
150+
{
151+
template: `
152+
<div>
153+
<app-component :elementtype = "'div,blue,30,div1'">Hello World</app-component>
154+
<app-component :elementtype = "'h3,red,30,h3tag'">Hello Peter</app-component>
155+
<app-component :elementtype = "'p,green,30,ptag'">Hello John</app-component>
156+
<app-component :elementtype = "'div,violet,30,divtag'">Hello Herry</app-component>
157+
</div>
158+
`,
159+
},
160+
mountOptions,
161+
)
162+
163+
cy.contains('h3', 'Hello Peter').should(
164+
'have.attr',
165+
'style',
166+
'color:red;font-size:30;',
167+
)
168+
169+
cy.contains('p', 'Hello John').should(
170+
'have.attr',
171+
'style',
172+
'color:green;font-size:30;',
173+
)
174+
})
175+
176+
it('mounts just the component and passes props', () => {
177+
mount(appComponent, {
178+
propsData: {
179+
elementtype: 'h3,red,30,h3tag',
180+
},
181+
})
182+
// the component appears and the styling is applied
183+
cy.contains('<EMPTY>').should(
184+
'have.attr',
185+
'style',
186+
'color:red;font-size:30;',
187+
)
188+
})
189+
})

src/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ const mountVue = (component, optionsOrProps = {}) => {
124124
component.store = resetStoreVM(Vue, component)
125125
}
126126

127+
// render function components should be market to be properly initialized
128+
// https://github.com/bahmutov/cypress-vue-unit-test/issues/313
129+
if (
130+
Cypress._.isPlainObject(component) &&
131+
Cypress._.isFunction(component.render)
132+
) {
133+
component._compiled = true
134+
}
135+
127136
return cy.window({ log: false }).then((win) => {
128137
win.Vue = Vue
129138

0 commit comments

Comments
 (0)