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(pathToSrc, pathToStories)
|
70 | const either = writeFile(`${pathToStories}/index.js`, content)
|
71 | return either.isLeft() ? either : Either.Right(fileList)
|
72 | }
|
73 |
|
74 |
|
75 | const requireTestGenerator = `const {testGenerator} = require('spdt/lib/test-generator')
|
76 | `
|
77 |
|
78 | const replaceStoryToFixture = (file) => file.replace('.story.', '.fixture.')
|
79 |
|
80 | const generateTestCode = (config, index) => `
|
81 | const fixtures${index} = require('${config.pathToFixture}')
|
82 | .default
|
83 |
|
84 | testGenerator({
|
85 | fixtures: fixtures${index},
|
86 | file: '${config.pathToFile}',
|
87 | componentName: '${config.componentName}',
|
88 | })
|
89 | `
|
90 |
|
91 | function capitalize(str) {
|
92 | const capitalizer = R.compose(
|
93 | R.join(''),
|
94 | R.juxt([
|
95 | R.compose(
|
96 | R.toUpper,
|
97 | R.head,
|
98 | ),
|
99 | R.tail,
|
100 | ]),
|
101 | )
|
102 |
|
103 | return R.ifElse(R.equals(null), R.identity, capitalizer)(str)
|
104 | }
|
105 |
|
106 | function toPascalCase(str) {
|
107 | const compose = R.compose(
|
108 | R.join(''),
|
109 | R.map(capitalize),
|
110 | R.split(/-|_|\s/),
|
111 | )
|
112 | return compose(str)
|
113 | }
|
114 |
|
115 | const getFileName = R.compose(
|
116 | toPascalCase,
|
117 | R.head,
|
118 | R.split('.'),
|
119 | R.last,
|
120 | R.split('/'),
|
121 | )
|
122 |
|
123 | function generateContentForTestIndex(pathToSrc, pathToTestIndex) {
|
124 | const fileList = recFindByExt(pathToSrc, STORY_EXT)
|
125 | const convertToRelativeFromTestIndex = convertToRelative(pathToTestIndex)
|
126 |
|
127 | const convertToConfig = (file) => ({
|
128 | pathToFixture: replaceStoryToFixture(convertToRelativeFromTestIndex(file)),
|
129 | pathToFile: convertToRelativeFromTestIndex(file),
|
130 | componentName: getFileName(file),
|
131 | })
|
132 |
|
133 | const convertAndGenerateTestCode = (file, index) => generateTestCode(convertToConfig(file), index)
|
134 |
|
135 | const e2eGeneratorContent = fileList.map(convertAndGenerateTestCode).join('')
|
136 | const content = requireTestGenerator.concat(e2eGeneratorContent)
|
137 | return {
|
138 | fileList,
|
139 | content,
|
140 | }
|
141 | }
|
142 |
|
143 | function generateTestIndex(pathToSrc, pathToTestIndex) {
|
144 | const config = getConfig()
|
145 | pathToSrc = pathToSrc || config.pathToSrc
|
146 | pathToTestIndex = pathToTestIndex || config.pathToTestIndex
|
147 | debug(`generateTestIndex config=${JSON.stringify(config)}`)
|
148 |
|
149 | const { content, fileList } = generateContentForTestIndex(pathToSrc, pathToTestIndex)
|
150 | const either = writeFile(`${pathToTestIndex}/${config.testIndexName}`, content)
|
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 | }
|