Skip to content

Commit

Permalink
refactor(init): refactor karma init (#2998)
Browse files Browse the repository at this point in the history
  • Loading branch information
lusarz authored and johnjbarton committed May 21, 2018
1 parent 6847ca0 commit a053570
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 106 deletions.
100 changes: 42 additions & 58 deletions lib/init.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
var readline = require('readline')
var path = require('path')
var glob = require('glob')
var mm = require('minimatch')
var exec = require('child_process').exec
'use strict'

var helper = require('./helper')
var logger = require('./logger')
const readline = require('readline')
const path = require('path')
const glob = require('glob')
const mm = require('minimatch')
const exec = require('child_process').exec

var log = logger.create('init')
const helper = require('./helper')
const logger = require('./logger')

var StateMachine = require('./init/state_machine')
var COLOR_SCHEME = require('./init/color_schemes')
var formatters = require('./init/formatters')
const log = logger.create('init')
const logQueue = require('./init/log-queue')

const StateMachine = require('./init/state_machine')
const COLOR_SCHEME = require('./init/color_schemes')
const formatters = require('./init/formatters')

// TODO(vojta): coverage
// TODO(vojta): html preprocessors
// TODO(vojta): SauceLabs
// TODO(vojta): BrowserStack

var logQueue = []
var printLogQueue = function () {
while (logQueue.length) {
logQueue.shift()()
}
}

var NODE_MODULES_DIR = path.resolve(__dirname, '../..')

// Karma is not in node_modules, probably a symlink,
Expand All @@ -33,7 +29,7 @@ if (!/node_modules$/.test(NODE_MODULES_DIR)) {
NODE_MODULES_DIR = path.resolve('node_modules')
}

var installPackage = function (pkgName) {
function installPackage (pkgName) {
// Do not install if already installed.
try {
require(NODE_MODULES_DIR + '/' + pkgName)
Expand All @@ -42,7 +38,7 @@ var installPackage = function (pkgName) {

log.debug('Missing plugin "%s". Installing...', pkgName)

var options = {
const options = {
cwd: path.resolve(NODE_MODULES_DIR, '..')
}

Expand All @@ -65,22 +61,22 @@ var installPackage = function (pkgName) {
})
}

var validatePattern = function (pattern) {
function validatePattern (pattern) {
if (!glob.sync(pattern).length) {
log.warn('There is no file matching this pattern.\n')
}
}

var validateBrowser = function (name) {
function validateBrowser (name) {
// TODO(vojta): check if the path resolves to a binary
installPackage('karma-' + name.toLowerCase().replace('canary', '') + '-launcher')
}

var validateFramework = function (name) {
function validateFramework (name) {
installPackage('karma-' + name)
}

var validateRequireJs = function (useRequire) {
function validateRequireJs (useRequire) {
if (useRequire) {
validateFramework('requirejs')
}
Expand Down Expand Up @@ -127,9 +123,7 @@ var questions = [{
hint: 'This will generate test-main.js/coffee that configures RequireJS and starts the tests.',
options: ['no', 'yes'],
boolean: true,
condition: function (answers) {
return answers.requirejs
}
condition: answers => answers.requirejs
}, {
id: 'includedFiles',
question: 'Which files do you want to include with <script> tag ?',
Expand All @@ -138,9 +132,7 @@ var questions = [{
'Enter empty string to move to the next question.',
multiple: true,
validate: validatePattern,
condition: function (answers) {
return answers.requirejs && !answers.generateTestMain
}
condition: answers => answers.requirejs && !answers.generateTestMain
}, {
id: 'autoWatch',
question: 'Do you want Karma to watch all the files and run the tests on change ?',
Expand All @@ -149,18 +141,18 @@ var questions = [{
boolean: true
}]

var getBasePath = function (configFilePath, cwd) {
var configParts = path.dirname(configFilePath).split(path.sep)
var cwdParts = cwd.split(path.sep)
var base = []
function getBasePath (configFilePath, cwd) {
const configParts = path.dirname(configFilePath).split(path.sep)
const cwdParts = cwd.split(path.sep)
const base = []

while (configParts.length && configParts[0] === cwdParts[0]) {
configParts.shift()
cwdParts.shift()
}

while (configParts.length) {
var part = configParts.shift()
const part = configParts.shift()
if (part === '..') {
base.unshift(cwdParts.pop())
} else if (part !== '.') {
Expand All @@ -171,8 +163,8 @@ var getBasePath = function (configFilePath, cwd) {
return base.join(path.sep)
}

var processAnswers = function (answers, basePath, testMainFile) {
var processedAnswers = {
function processAnswers (answers, basePath, testMainFile) {
const processedAnswers = {
basePath: basePath,
files: answers.files,
onlyServedFiles: [],
Expand All @@ -198,10 +190,8 @@ var processAnswers = function (answers, basePath, testMainFile) {
}
}

var allPatterns = answers.files.concat(answers.includedFiles || [])
if (allPatterns.some(function (pattern) {
return mm(pattern, '**/*.coffee')
})) {
const allPatterns = answers.files.concat(answers.includedFiles || [])
if (allPatterns.some(pattern => mm(pattern, '**/*.coffee'))) {
installPackage('karma-coffee-preprocessor')
processedAnswers.preprocessors['**/*.coffee'] = ['coffee']
}
Expand All @@ -212,18 +202,14 @@ var processAnswers = function (answers, basePath, testMainFile) {
exports.init = function (config) {
logger.setupFromConfig(config)

var colorScheme = COLOR_SCHEME.ON

if (helper.isDefined(config.colors)) {
colorScheme = config.colors ? COLOR_SCHEME.ON : COLOR_SCHEME.OFF
}
const colorScheme = !helper.isDefined(config.colors) || config.colors ? COLOR_SCHEME.ON : COLOR_SCHEME.OFF
// need to be registered before creating readlineInterface
process.stdin.on('keypress', function (s, key) {
sm.onKeypress(key)
})

var rli = readline.createInterface(process.stdin, process.stdout)
var sm = new StateMachine(rli, colorScheme)
const rli = readline.createInterface(process.stdin, process.stdout)
const sm = new StateMachine(rli, colorScheme)

rli.on('line', sm.onLine.bind(sm))

Expand All @@ -233,17 +219,15 @@ exports.init = function (config) {
process.exit(0)
})

sm.on('next_question', printLogQueue)

sm.process(questions, function (answers) {
var cwd = process.cwd()
var configFile = config.configFile || 'karma.conf.js'
var isCoffee = path.extname(configFile) === '.coffee'
var testMainFile = isCoffee ? 'test-main.coffee' : 'test-main.js'
var formatter = formatters.createForPath(configFile)
var processedAnswers = processAnswers(answers, getBasePath(configFile, cwd), testMainFile)
var configFilePath = path.resolve(cwd, configFile)
var testMainFilePath = path.resolve(cwd, testMainFile)
const cwd = process.cwd()
const configFile = config.configFile || 'karma.conf.js'
const isCoffee = path.extname(configFile) === '.coffee'
const testMainFile = isCoffee ? 'test-main.coffee' : 'test-main.js'
const formatter = formatters.createForPath(configFile)
const processedAnswers = processAnswers(answers, getBasePath(configFile, cwd), testMainFile)
const configFilePath = path.resolve(cwd, configFile)
const testMainFilePath = path.resolve(cwd, testMainFile)

if (isCoffee) {
installPackage('coffee-script')
Expand Down
15 changes: 15 additions & 0 deletions lib/init/log-queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict'

const logQueue = []
function printLogQueue () {
logQueue.forEach(log => log())
logQueue.length = 0
}

function push (log) {
logQueue.push(log)
}

module.exports = {
printLogQueue, push
}
98 changes: 50 additions & 48 deletions lib/init/state_machine.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,71 @@
var util = require('util')
var EventEmitter = require('events').EventEmitter

var StateMachine = function (rli, colors) {
var questions
var currentQuestion
var answers
var currentOptions
var currentOptionsPointer
var currentQuestionId
var done

EventEmitter.call(this)

var showPrompt = function () {
rli.write(colors.ANSWER)
rli.prompt()
'use strict'

const logQueue = require('./log-queue')

var questions
var currentQuestion
var answers
var currentOptions
var currentOptionsPointer
var currentQuestionId
var done

class StateMachine {
constructor (rli, colors) {
this.rli = rli
this.colors = colors
}

this.onKeypress = function (key) {
showPrompt () {
this.rli.write(this.colors.ANSWER)
this.rli.prompt()
}

onKeypress (key) {
if (!currentOptions || !key) {
return
}

if (key.name === 'tab' || key.name === 'right' || key.name === 'down') {
this.suggestNextOption()
this.suggestOption(currentOptionsPointer + 1)
} else if (key.name === 'left' || key.name === 'up') {
currentOptionsPointer = currentOptionsPointer + currentOptions.length - 2
this.suggestNextOption()
this.suggestOption(currentOptionsPointer - 1)
}

if (!key.ctrl && !key.meta && key.name !== 'enter' && key.name !== 'return') {
key.name = 'escape'
}
}

this.suggestNextOption = function () {
suggestOption (index) {
if (!currentOptions) {
return
}

currentOptionsPointer = (currentOptionsPointer + 1) % currentOptions.length
rli._deleteLineLeft()
rli._deleteLineRight()
rli.write(currentOptions[currentOptionsPointer])
if (index === -1) {
currentOptionsPointer = currentOptions.length - 1
} else if (index === currentOptions.length) {
currentOptionsPointer = 0
} else {
currentOptionsPointer = index
}

this.rli._deleteLineLeft()
this.rli._deleteLineRight()
this.rli.write(currentOptions[currentOptionsPointer])
}

this.kill = function () {
kill () {
currentOptions = null
currentQuestionId = null
rli.write('\n' + colors.RESET + '\n')
rli.close()
this.rli.write('\n' + this.colors.RESET + '\n')
this.rli.close()
}

this.onLine = function (line) {
onLine (line) {
if (currentQuestionId) {
rli.write(colors.RESET)
line = line.trim().replace(colors.ANSWER, '').replace(colors.RESET, '')
this.rli.write(this.colors.RESET)
line = line.trim().replace(this.colors.ANSWER, '').replace(this.colors.RESET, '')

if (currentOptions) {
currentOptionsPointer = currentOptions.indexOf(line)
Expand All @@ -80,7 +90,7 @@ var StateMachine = function (rli, colors) {
answers[currentQuestionId] = answers[currentQuestionId] || []
if (line !== null) {
answers[currentQuestionId].push(line)
showPrompt()
this.showPrompt()

if (currentOptions) {
currentOptions.splice(currentOptionsPointer, 1)
Expand All @@ -96,38 +106,32 @@ var StateMachine = function (rli, colors) {
}
}

this.nextQuestion = function () {
nextQuestion () {
currentQuestion = questions.shift()

while (currentQuestion && currentQuestion.condition && !currentQuestion.condition(answers)) {
currentQuestion = questions.shift()
}

this.emit('next_question', currentQuestion)
logQueue.printLogQueue()

if (currentQuestion) {
currentQuestionId = null

rli.write('\n' + colors.question(currentQuestion.question) + '\n')
rli.write(currentQuestion.hint + '\n')
showPrompt()
this.rli.write('\n' + this.colors.question(currentQuestion.question) + '\n')
this.rli.write(currentQuestion.hint + '\n')
this.showPrompt()

currentOptions = currentQuestion.options || null
currentOptionsPointer = -1
currentQuestionId = currentQuestion.id

this.suggestNextOption()
this.suggestOption(0)
} else {
currentQuestionId = null
currentOptions = null

// end
this.kill()
done(answers)
}
}

this.process = function (_questions, _done) {
process (_questions, _done) {
questions = _questions
answers = {}
done = _done
Expand All @@ -136,6 +140,4 @@ var StateMachine = function (rli, colors) {
}
}

util.inherits(StateMachine, EventEmitter)

module.exports = StateMachine

0 comments on commit a053570

Please sign in to comment.