Skip to content

Commit 40e5ac0

Browse files
authored
feat: component options, svg example, global style (#41)
1 parent 4352a4b commit 40e5ac0

File tree

4 files changed

+144
-10
lines changed

4 files changed

+144
-10
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@ npm install --save-dev @cypress/webpack-preprocessor
2222

2323
This component adaptor is meant for [Svelte v3](https://svelte.dev/blog/svelte-3-rethinking-reactivity). If you need Svelte v2 support, check out branch [svelte-v2](https://github.com/bahmutov/cypress-svelte-unit-test/tree/svelte-v2)
2424

25+
## Use
26+
27+
Import your Svelte component and mount using the provided function. Pass [component options](https://svelte.dev/docs#Creating_a_component) and global document options (like a global CSS)
28+
29+
```js
30+
/// <reference types="cypress" />
31+
import App from '../components/ChainedBalls.svelte'
32+
import mount from 'cypress-svelte-unit-test'
33+
34+
describe('SVG animation', () => {
35+
it('shows chained balls', () => {
36+
cy.viewport(960, 500)
37+
const style = `
38+
line {
39+
stroke: gray;
40+
stroke-width: 2px;
41+
}
42+
`
43+
mount(App, {
44+
props: {
45+
width: 960,
46+
height: 500
47+
}
48+
}, { style })
49+
cy.get('circle').should('have.length', 50)
50+
})
51+
})
52+
```
53+
2554
## Examples
2655

2756
Svelte components copied from [https://svelte.dev/examples](https://svelte.dev/examples)
@@ -35,6 +64,7 @@ Component | spec
3564
[ReactiveAssignments.svelte](cypress/components/ReactiveAssignments.svelte) | [reactive-assignments-spec.js](cypress/integration/reactive-assignments-spec.js)
3665
[ReactiveDeclarations.svelte](cypress/components/ReactiveDeclarations.svelte) | [reactive-declarations-spec.js](cypress/integration/reactive-declarations-spec.js)
3766
[ReactiveStatements.svelte](cypress/components/ReactiveStatements.svelte) | [reactive-statements-spec.js](cypress/integration/reactive-statements-spec.js)
67+
[ChainedBalls.svelte](cypress/components/ChainedBalls.svelte) | [chained-balls-spec.js](cypress/integration/chained-balls-spec.js)
3868

3969
## Details
4070

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!-- Example copied from
2+
- https://bl.ocks.org/curran/71dfa9cf182473fd2cb2f2d027f3828e
3+
- https://twitter.com/currankelleher/status/1120794510508740609 -->
4+
5+
<style>
6+
h1 {
7+
color: purple;
8+
}
9+
</style>
10+
11+
<script>
12+
// don't forget to pass "width" and "height" as props
13+
export let width;
14+
export let height;
15+
export let n = 50;
16+
17+
let numbers = [];
18+
19+
const f = (x, t) => Math.sin(x * t + t) * 200;
20+
21+
const setNumbers = () => {
22+
for (let i = 0; i < n; i++) {
23+
const x = i / n;
24+
const t = Date.now() / 1000;
25+
numbers[i] = f(x, t);
26+
}
27+
};
28+
29+
const animate = () => {
30+
setNumbers();
31+
requestAnimationFrame(animate);
32+
};
33+
animate();
34+
</script>
35+
36+
<svg width={width} height={height}>
37+
{#each numbers as y, i}
38+
<circle
39+
cx={i / n * width}
40+
cy={y + height / 2}
41+
r="10"
42+
/>
43+
{#if i < n - 1}
44+
<line
45+
x1={i / n * width}
46+
y1={y + height / 2}
47+
x2={(i + 1) / n * width}
48+
y2={numbers[i + 1] + height / 2}
49+
/>
50+
{/if}
51+
{/each}
52+
</svg>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// <reference types="cypress" />
2+
import App from '../components/ChainedBalls.svelte'
3+
import mount from '../../src'
4+
5+
/* eslint-env mocha */
6+
describe('SVG animation', () => {
7+
it('shows chained balls', () => {
8+
cy.viewport(960, 500)
9+
const style = `
10+
body {
11+
margin: 0;
12+
}
13+
line {
14+
stroke: gray;
15+
stroke-width: 2px;
16+
}
17+
`
18+
mount(
19+
App,
20+
{
21+
props: {
22+
width: 960,
23+
height: 500
24+
}
25+
},
26+
{
27+
style
28+
}
29+
)
30+
cy.get('circle').should('have.length', 50)
31+
})
32+
})

src/index.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function setAlert (w) {
1111
return w
1212
}
1313

14-
export default function mount (Component, data, slots, store) {
14+
export default function mount (Component, options = {}, docOptions = {}) {
1515
const html = `
1616
<div id="app"></div>
1717
`
@@ -26,20 +26,43 @@ export default function mount (Component, data, slots, store) {
2626

2727
cy.get('#app', { log: false }).should('exist')
2828
return cy.document({ log: false }).then(doc => {
29-
Cypress.component = new Component({
30-
target: doc.getElementById('app'),
31-
data,
32-
slots,
33-
store
29+
const allOptions = Object.assign({}, options, {
30+
target: doc.getElementById('app')
3431
})
32+
Cypress.component = new Component(allOptions)
3533
copyStyles(Component)
34+
35+
if (docOptions.style) {
36+
addGlobalStyle(docOptions.style)
37+
}
3638
})
3739
}
3840

41+
/**
42+
* Adds global CSS style.
43+
*/
44+
function addGlobalStyle (css) {
45+
const style = document.createElement('style')
46+
style.type = 'text/css'
47+
style.appendChild(document.createTextNode(css))
48+
49+
const appIframe = getAppIframe()
50+
const head = appIframe.contentDocument.querySelector('head')
51+
head.appendChild(style)
52+
}
53+
3954
// having weak reference to styles prevents garbage collection
4055
// and "losing" styles when the next test starts
4156
const stylesCache = new Map()
4257

58+
function getAppIframe () {
59+
const parentDocument = window.parent.document
60+
const projectName = Cypress.config('projectName')
61+
const appIframeId = `Your App: '${projectName}'`
62+
const appIframe = parentDocument.getElementById(appIframeId)
63+
return appIframe
64+
}
65+
4366
function copyStyles (component) {
4467
const hash = component
4568

@@ -60,10 +83,7 @@ function copyStyles (component) {
6083
return
6184
}
6285

63-
const parentDocument = window.parent.document
64-
const projectName = Cypress.config('projectName')
65-
const appIframeId = `Your App: '${projectName}'`
66-
const appIframe = parentDocument.getElementById(appIframeId)
86+
const appIframe = getAppIframe()
6787
const head = appIframe.contentDocument.querySelector('head')
6888
styles.forEach(style => {
6989
head.appendChild(style)

0 commit comments

Comments
 (0)