-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
125 lines (109 loc) · 3.53 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { stripIndent } from 'common-tags'
// having weak reference to styles prevents garbage collection
// and "losing" styles when the next test starts
const stylesCache = new Map()
const copyStyles = component => {
// need to find same component when component is recompiled
// by the JSX preprocessor. Thus have to use something else,
// like component name
// const hash = component.type.name
const hash = component
let styles = document.querySelectorAll('head style')
if (styles.length) {
console.log('injected %d styles', styles.length)
stylesCache.set(hash, styles)
} else {
console.log('No styles injected for this component, checking cache')
if (stylesCache.has(hash)) {
styles = stylesCache.get(hash)
} else {
styles = null
}
}
if (!styles) {
return
}
const parentDocument = window.parent.document
const projectName = Cypress.config('projectName')
const appIframeId = `Your App: '${projectName}'`
const appIframe = parentDocument.getElementById(appIframeId)
const head = appIframe.contentDocument.querySelector('head')
styles.forEach(style => {
head.appendChild(style)
})
}
function setXMLHttpRequest (w) {
// by grabbing the XMLHttpRequest from app's iframe
// and putting it here - in the test iframe
// we suddenly get spying and stubbing 😁
window.XMLHttpRequest = w.XMLHttpRequest
return w
}
function setAlert (w) {
window.alert = w.alert
return w
}
export const mount = (state, actions, view) => {
if (!actions) {
// we always want to have an actions object so we
// can attach _getState utility function
actions = {}
}
// TODO stop hard coding Hyperapp version, grab from the "node_modules"
const html = stripIndent`
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/hyperapp@1.2.0/dist/hyperapp.js"></script>
</body>
`
const document = cy.state('document')
document.write(html)
document.close()
// add a utility action to get the current state
if (!actions._getState) {
const _getState = () => state => state
actions = Object.assign({}, actions, { _getState })
}
// force waiting for window.hyperapp to exist before anything else happens
cy
.window({ log: false })
.its('hyperapp')
.should('be.an', 'object')
// now can attach our handlers
cy
.window({ log: false })
.then(setXMLHttpRequest)
.then(setAlert)
.its('hyperapp.app')
.then(app => {
const el = document.getElementById('app')
const main = app(state, actions, view, el)
// wrap every hyper action with `cy.then` to
// make sure it goes through the Cypress command queue
// allows things like the example below to just work
// Cypress.main.setText('foo')
// cy.contains('foo')
// Cypress.main.setText('bar')
// cy.contains('bar')
Cypress.main = {}
Object.keys(main).forEach(name => {
const action = main[name]
Cypress.main[name] = function queueAction () {
// should we log arguments?
cy.log(`action: ${name}`)
return cy.then(() => action.apply(null, arguments))
}
})
return Cypress.main
})
cy.get('#app', { log: false }).should('be.visible')
// picostyle dom is more complex
// picostyle inserts a style into the document's head
// but then it actually inserts new CSS rules when the view instantiates
// so we need to _observe_ test document style and on added
// CSS rules copy them
copyStyles(view)
}