aboutsummaryrefslogblamecommitdiffstats
path: root/gentests.js
blob: 08232e10ff405fc1f532fe2c1503d7ff5146d562 (plain) (tree)









































































































































































































































                                                                                                                     
const fs = require('fs')
const async = require('async')
const path = require('path')
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 rootPath = path.join(__dirname, 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) => {
    let [, 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))
  
  let sFileMethodNames
  async.each(sFiles, async (sFile, cb) => {
    console.log(`sFile`, sFile);
    let [, sRootPath, sPath] = sFile.match(/^(.+\/)([^/]+)$/)
    
    let testFilePath = sPath.replace('.', '-').replace('.', '.test.')

    await promisify(fs.readFile)(
      __dirname + '/' + sFile,
      'utf8',
      async (err, result) => {
        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'}

  })

})`
}