1 | const path = require('path')
|
2 | const fs = require('fs')
|
3 | const R = require('ramda')
|
4 | const { Either } = require('monet')
|
5 | const debug = require('debug')('spdt')
|
6 | const { getConfig } = require('./config')
|
7 |
|
8 | const STORY_EXT = /\.story\.[tj]sx?/
|
9 |
|
10 |
|
11 | function recFindByExt(base, ext, files, result) {
|
12 | files = files || fs.readdirSync(base)
|
13 | result = result || []
|
14 |
|
15 | files.forEach((file) => {
|
16 | const newbase = path.join(base, file)
|
17 | if (fs.statSync(newbase).isDirectory()) {
|
18 | result = recFindByExt(newbase, ext, fs.readdirSync(newbase), result)
|
19 | } else {
|
20 |
|
21 | if (RegExp(ext).test(file)) {
|
22 | result.push(newbase)
|
23 | }
|
24 | }
|
25 | })
|
26 | return result
|
27 | }
|
28 |
|
29 |
|
30 |
|
31 | const convertToRelative = R.curry((from, file) => path.relative(from, file))
|
32 | const generateCode = (file) => `require('${file}').default(
|
33 | storyGenerator,
|
34 | )`
|
35 |
|
36 | const requireStoryBookGenerator = `const {storyGenerator} = require('spdt')
|
37 | `
|
38 |
|
39 | function generateContentForStoryIndex(pathToSrc, pathToStories) {
|
40 | const fileList = recFindByExt(pathToSrc, STORY_EXT)
|
41 |
|
42 | const convertAndGenerate = R.compose(
|
43 | generateCode,
|
44 | convertToRelative(pathToStories),
|
45 | )
|
46 | const generatedCode = fileList.map(convertAndGenerate).join('\n')
|
47 | const content = requireStoryBookGenerator.concat(generatedCode, '\n')
|
48 | return {
|
49 | fileList,
|
50 | content,
|
51 | }
|
52 | }
|
53 |
|
54 | function writeFile(file, content) {
|
55 | try {
|
56 | fs.writeFileSync(file, content)
|
57 | return Either.Right(true)
|
58 | } catch (err) {
|
59 | return Either.Left(err)
|
60 | }
|
61 | }
|
62 |
|
63 | function generateStoryIndex(pathToSrc, pathToStories) {
|
64 | const config = getConfig()
|
65 | pathToSrc = pathToSrc || config.pathToSrc
|
66 | pathToStories = pathToStories || config.pathToStories
|
67 | debug(`generateStoryIndex config=${JSON.stringify(config)}`)
|
68 |
|
69 | const { content, fileList } = generateContentForStoryIndex(
|
70 | pathToSrc,
|
71 | pathToStories,
|
72 | )
|
73 | const either = writeFile(`${pathToStories}/index.js`, content)
|
74 | return either.isLeft() ? either : Either.Right(fileList)
|
75 | }
|
76 |
|
77 |
|
78 | const requireTestGenerator = `const {testGenerator} = require('spdt/lib/test-generator.js')
|
79 | `
|
80 |
|
81 | const replaceStoryToFixture = (file) => file.replace('.story.', '.fixture.')
|
82 |
|
83 | const generateTestCode = (config, index) => `
|
84 | const fixtures${index} = require('${config.pathToFixture}')
|
85 | .default
|
86 |
|
87 | testGenerator({
|
88 | fixtures: fixtures${index},
|
89 | file: '${config.pathToFile}',
|
90 | componentName: '${config.componentName}',
|
91 | })
|
92 | `
|
93 |
|
94 | function capitalize(str) {
|
95 | const capitalizer = R.compose(
|
96 | R.join(''),
|
97 | R.juxt([R.compose(R.toUpper, R.head), R.tail]),
|
98 | )
|
99 |
|
100 | return R.ifElse(R.equals(null), R.identity, capitalizer)(str)
|
101 | }
|
102 |
|
103 | function toPascalCase(str) {
|
104 | const compose = R.compose(R.join(''), R.map(capitalize), R.split(/-|_|\s/))
|
105 | return compose(str)
|
106 | }
|
107 |
|
108 | const getFileName = R.compose(
|
109 | toPascalCase,
|
110 | R.head,
|
111 | R.split('.'),
|
112 | R.last,
|
113 | R.split('/'),
|
114 | )
|
115 |
|
116 | function generateContentForTestIndex(pathToSrc, pathToTestIndex) {
|
117 | const fileList = recFindByExt(pathToSrc, STORY_EXT)
|
118 | const convertToRelativeFromTestIndex = convertToRelative(pathToTestIndex)
|
119 |
|
120 | const convertToConfig = (file) => ({
|
121 | pathToFixture: replaceStoryToFixture(convertToRelativeFromTestIndex(file)),
|
122 | pathToFile: convertToRelativeFromTestIndex(file),
|
123 | componentName: getFileName(file),
|
124 | })
|
125 |
|
126 | const convertAndGenerateTestCode = (file, index) =>
|
127 | generateTestCode(convertToConfig(file), index)
|
128 |
|
129 | const e2eGeneratorContent = fileList.map(convertAndGenerateTestCode).join('')
|
130 | const content = requireTestGenerator.concat(e2eGeneratorContent)
|
131 | return {
|
132 | fileList,
|
133 | content,
|
134 | }
|
135 | }
|
136 |
|
137 | function generateTestIndex(pathToSrc, pathToTestIndex) {
|
138 | const config = getConfig()
|
139 | pathToSrc = pathToSrc || config.pathToSrc
|
140 | pathToTestIndex = pathToTestIndex || config.pathToTestIndex
|
141 | debug(`generateTestIndex config=${JSON.stringify(config)}`)
|
142 |
|
143 | const { content, fileList } = generateContentForTestIndex(
|
144 | pathToSrc,
|
145 | pathToTestIndex,
|
146 | )
|
147 | const either = writeFile(
|
148 | `${pathToTestIndex}/${config.testIndexName}`,
|
149 | content,
|
150 | )
|
151 | return either.isLeft() ? either : Either.Right(fileList)
|
152 | }
|
153 |
|
154 |
|
155 | module.exports = {
|
156 | capitalize,
|
157 | generateContentForStoryIndex,
|
158 | generateContentForTestIndex,
|
159 | generateStoryIndex,
|
160 | generateTestIndex,
|
161 | toPascalCase,
|
162 | }
|