const fs = require('fs') const path = require('path') const async = require('async') const promisify = require('pify') // start(/\.selectors.js/, generateSelectorTest).catch(console.error) // start(/\.utils.js/, generateUtilTest).catch(console.error) startContainer(/\.container.js/, generateContainerTest).catch(console.error) async function getAllFileNames (dirName) { const allNames = (await promisify(fs.readdir)(dirName)) const fileNames = allNames.filter(name => name.match(/^.+\./)) const dirNames = allNames.filter(name => name.match(/^[^.]+$/)) const fullPathDirNames = dirNames.map(d => `${dirName}/${d}`) const subNameArrays = await promisify(async.map)(fullPathDirNames, getAllFileNames) let subNames = [] subNameArrays.forEach(subNameArray => { subNames = [...subNames, ...subNameArray] }) return [ ...fileNames.map(name => dirName + '/' + name), ...subNames, ] } /* async function start (fileRegEx, testGenerator) { const fileNames = await getAllFileNames('./ui/app') const sFiles = fileNames.filter(name => name.match(fileRegEx)) let sFileMethodNames let testFilePath async.each(sFiles, async (sFile, cb) => { const [, sRootPath, sPath] = sFile.match(/^(.+\/)([^/]+)$/) sFileMethodNames = Object.keys(require(__dirname + '/' + sFile)) testFilePath = sPath.replace('.', '-').replace('.', '.test.') await promisify(fs.writeFile)( `${__dirname}/${sRootPath}tests/${testFilePath}`, testGenerator(sPath, sFileMethodNames), 'utf8' ) }, (err) => { console.log(err) }) } */ async function startContainer (fileRegEx, testGenerator) { const fileNames = await getAllFileNames('./ui/app') const sFiles = fileNames.filter(name => name.match(fileRegEx)) async.each(sFiles, async (sFile, cb) => { console.log(`sFile`, sFile) const [, sRootPath, sPath] = sFile.match(/^(.+\/)([^/]+)$/) const testFilePath = sPath.replace('.', '-').replace('.', '.test.') await promisify(fs.readFile)( path.join(__dirname, sFile), 'utf8', async (err, result) => { if (err) { console.log('Error: ', err) } else { console.log(`result`, result.length) const returnObjectStrings = result .match(/return\s(\{[\s\S]+?})\n}/g) .map(str => { return str .slice(0, str.length - 1) .slice(7) .replace(/\n/g, '') .replace(/\s\s+/g, ' ') }) const mapStateToPropsAssertionObject = returnObjectStrings[0] .replace(/\w+:\s\w+\([\w,\s]+\),/g, str => { const strKey = str.match(/^\w+/)[0] return strKey + ': \'mock' + str.match(/^\w+/)[0].replace(/^./, c => c.toUpperCase()) + ':mockState\',\n' }) .replace(/{\s\w.+/, firstLinePair => `{\n ${firstLinePair.slice(2)}`) .replace(/\w+:.+,/g, s => ` ${s}`) .replace(/}/g, s => ` ${s}`) let mapDispatchToPropsMethodNames if (returnObjectStrings[1]) { mapDispatchToPropsMethodNames = returnObjectStrings[1].match(/\s\w+:\s/g).map(str => str.match(/\w+/)[0]) } const proxyquireObject = ('{\n ' + result .match(/import\s{[\s\S]+?}\sfrom\s.+/g) .map(s => s.replace(/\n/g, '')) .map((s, i) => { const proxyKeys = s.match(/{.+}/)[0].match(/\w+/g) return '\'' + s.match(/'(.+)'/)[1] + '\': { ' + (proxyKeys.length > 1 ? '\n ' + proxyKeys.join(': () => {},\n ') + ': () => {},\n ' : proxyKeys[0] + ': () => {},') + ' }' }) .join(',\n ') + '\n}') .replace('{ connect: () => {}, },', `{ connect: (ms, md) => { mapStateToProps = ms mapDispatchToProps = md return () => ({}) }, },`) // console.log(`proxyquireObject`, proxyquireObject); // console.log(`mapStateToPropsAssertionObject`, mapStateToPropsAssertionObject); // console.log(`mapDispatchToPropsMethodNames`, mapDispatchToPropsMethodNames); const containerTest = generateContainerTest(sPath, { mapStateToPropsAssertionObject, mapDispatchToPropsMethodNames, proxyquireObject, }) // console.log(`containerTest`, `${__dirname}/${sRootPath}tests/${testFilePath}`, containerTest); console.log('----') console.log(`sRootPath`, sRootPath) console.log(`testFilePath`, testFilePath) await promisify(fs.writeFile)( `${__dirname}/${sRootPath}tests/${testFilePath}`, containerTest, 'utf8' ) } } ) }, (err) => { console.log('123', err) }) } /* function generateMethodList (methodArray) { return methodArray.map(n => ' ' + n).join(',\n') + ',' } function generateMethodDescribeBlock (methodName, index) { const describeBlock = `${index ? ' ' : ''}describe('${methodName}()', () => { it('should', () => { const state = {} assert.equal(${methodName}(state), ) }) })` return describeBlock } */ function generateDispatchMethodDescribeBlock (methodName, index) { const describeBlock = `${index ? ' ' : ''}describe('${methodName}()', () => { it('should dispatch an action', () => { mapDispatchToPropsObject.${methodName}() assert(dispatchSpy.calledOnce) }) })` return describeBlock } /* function generateMethodDescribeBlocks (methodArray) { return methodArray .map((methodName, index) => generateMethodDescribeBlock(methodName, index)) .join('\n\n') } */ function generateDispatchMethodDescribeBlocks (methodArray) { return methodArray .map((methodName, index) => generateDispatchMethodDescribeBlock(methodName, index)) .join('\n\n') } /* function generateSelectorTest (name, methodArray) { return `import assert from 'assert' import { ${generateMethodList(methodArray)} } from '../${name}' describe('${name.match(/^[^.]+/)} selectors', () => { ${generateMethodDescribeBlocks(methodArray)} })` } function generateUtilTest (name, methodArray) { return `import assert from 'assert' import { ${generateMethodList(methodArray)} } from '../${name}' describe('${name.match(/^[^.]+/)} utils', () => { ${generateMethodDescribeBlocks(methodArray)} })` } */ function generateContainerTest (sPath, { mapStateToPropsAssertionObject, mapDispatchToPropsMethodNames, proxyquireObject, }) { return `import assert from 'assert' import proxyquire from 'proxyquire' import sinon from 'sinon' let mapStateToProps let mapDispatchToProps proxyquire('../${sPath}', ${proxyquireObject}) describe('${sPath.match(/^[^.]+/)} container', () => { describe('mapStateToProps()', () => { it('should map the correct properties to props', () => { assert.deepEqual(mapStateToProps('mockState'), ${mapStateToPropsAssertionObject}) }) }) describe('mapDispatchToProps()', () => { let dispatchSpy let mapDispatchToPropsObject beforeEach(() => { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) }) ${mapDispatchToPropsMethodNames ? generateDispatchMethodDescribeBlocks(mapDispatchToPropsMethodNames) : 'delete'} }) })` }