UNPKG

5.29 kBJavaScriptView Raw
1const R = require('ramda')
2const fs = require('fs')
3const debug = require('debug')('spdt')
4const { getConfig, STORYBOOK_PORT } = require('./config')
5
6const saveFile = (fileName, content) => {
7 fs.writeFile(fileName, content, (err) => {
8 if (err) {
9 return debug(`error: ${err}`)
10 } else {
11 return debug(`File was saved: ${fileName}`)
12 }
13 })
14}
15
16const generateImports = () => `const TIMEOUT = 5000
17`
18
19const generateDescribe = (componentName, fixtureName, itTests) => `
20describe(
21 '${componentName} - fixture ${fixtureName}',
22 () => {
23 let page
24 let iFrame
25 beforeAll(async () => {
26 // eslint-disable-next-line no-underscore-dangle
27 page = await global.__BROWSER__.newPage()
28 // prettier-ignore
29 await page.goto('http://localhost:${STORYBOOK_PORT}/?selectedKind=${componentName}&selectedStory=${fixtureName}')
30 const frames = await page.frames()
31 iFrame = frames.find((f) => f.name() === 'storybook-preview-iframe')
32 }, TIMEOUT)
33
34 afterAll(async () => {
35 await page.close()
36 })
37${itTests}
38 },
39 TIMEOUT,
40)
41`
42
43const testCheckSelectorObject = (strOrObj) => {
44 let selector
45 let length
46 if (typeof strOrObj === 'string') {
47 selector = strOrObj
48 length = 1
49 } else if (typeof strOrObj === 'object' && !Array.isArray(strOrObj)) {
50 ;({ length, selector } = strOrObj)
51 }
52
53 if (!selector || !length) {
54 return null
55 }
56 return `
57 it('should find component matching selector [${selector}] ${length} time(s)', async () => {
58 const components = await iFrame.$$('${selector}')
59 const expected = ${length}
60 expect(components).toHaveLength(expected)
61 })`
62}
63
64const testCheckSelector = (fixture) => {
65 const { checkSelector } = R.propOr({}, 'spdt', fixture)
66 if (!checkSelector) {
67 return null
68 }
69 if (typeof checkSelector === 'string') {
70 return testCheckSelectorObject(checkSelector)
71 }
72 if (Array.isArray(checkSelector)) {
73 return checkSelector.map(testCheckSelectorObject)
74 } else if (typeof checkSelector === 'object') {
75 return testCheckSelectorObject(checkSelector)
76 }
77 return null
78}
79
80const testCheckSvg = (fixture) => {
81 const { checkSvg } = R.propOr({}, 'spdt', fixture)
82 if (checkSvg !== true) {
83 return null
84 }
85 return `
86 it('should load component as <svg>', async () => {
87 const component = await iFrame.$('svg')
88 expect(component._remoteObject.description).toMatch('svg') // eslint-disable-line no-underscore-dangle
89 })`
90}
91
92const testCheckAxes = (fixture) => {
93 const { checkAxes } = R.propOr({}, 'spdt', fixture)
94 if (!Number.isInteger(checkAxes)) {
95 return null
96 }
97 return `
98 it('should have ${checkAxes} axes', async () => {
99 const axes = await iFrame.$$('g.axis')
100 const expected = ${checkAxes}
101 expect(axes).toHaveLength(expected)
102 })`
103}
104
105const testCheckBars = (fixture) => {
106 const { checkBars } = R.propOr({}, 'spdt', fixture)
107 if (checkBars !== true) {
108 return null
109 }
110 const checkBarsValue = R.pathOr(0, ['props', 'data', 'length'], fixture)
111 return `
112 it('should have ${checkBarsValue} bars according to fixture data', async () => {
113 const bars = await iFrame.$$('rect.bar')
114 const expected = ${checkBarsValue} // fixture.props.data.length
115 expect(bars).toHaveLength(expected)
116 })`
117}
118
119const testCheckArcs = (fixture) => {
120 const { checkArcs } = R.propOr({}, 'spdt', fixture)
121 if (checkArcs !== true) {
122 return null
123 }
124 const checkArcsValue = R.pathOr(0, ['props', 'data', 'length'], fixture)
125 return `
126 it('should have ${checkArcsValue} arcs according to fixture data', async () => {
127 const arcs = await iFrame.$$('path.arc')
128 const expected = ${checkArcsValue} // fixture.props.data.length
129 expect(arcs).toHaveLength(expected)
130 })`
131}
132
133// map a key in fixtures.[fixture name].spdt to respective function which generates an it test
134const testMapper = {
135 checkSelector: testCheckSelector,
136 checkSvg: testCheckSvg,
137 checkAxes: testCheckAxes,
138 checkBars: testCheckBars,
139 checkArcs: testCheckArcs,
140}
141
142const generateItTests = (fixture) => {
143 const result = []
144 const spdtKeys = Object.keys(R.propOr({}, 'spdt', fixture))
145 spdtKeys.forEach((checkItem) => testMapper[checkItem] && result.push(testMapper[checkItem](fixture)))
146 return result.join('')
147}
148
149function getFileName({ file, pathToTestIndex }) {
150 const config = getConfig()
151 const pathTo = pathToTestIndex || config.pathToTestIndex
152
153 const fileName = `${pathTo}/${file.replace('.story.', '.generated.spdt.')}`
154 return fileName
155}
156
157function generateContent({ fixtures, componentName }) {
158 const content = []
159 content.push(generateImports(componentName))
160
161 Object.keys(fixtures).forEach((fixtureName) => {
162 const itTests = generateItTests(fixtures[fixtureName])
163 content.push(generateDescribe(componentName, fixtureName, itTests))
164 })
165 return content
166}
167
168function testGenerator({ fixtures, file, componentName, pathToTestIndex }) {
169 const content = generateContent({ fixtures, componentName })
170 const fileName = getFileName({ file, pathToTestIndex })
171 saveFile(fileName, content.join(''))
172}
173
174module.exports = {
175 testGenerator,
176 getFileName,
177 generateContent,
178 testCheckArcs,
179 testCheckBars,
180 testCheckSvg,
181 testCheckSelector,
182 testCheckAxes,
183 saveFile,
184}