Skip to content

Commit

Permalink
Started refactoring out a filewatcher object. Also made use of event …
Browse files Browse the repository at this point in the history
…emitters everywhere.
  • Loading branch information
airportyh committed Apr 26, 2012
1 parent 1385050 commit 188d09d
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 268 deletions.
36 changes: 15 additions & 21 deletions lib/appviewcharm.js
Expand Up @@ -4,17 +4,19 @@ var charm = require('charm')(process)
, tty = require('tty')
, log = require('winston')
, getTermSize = require('./gettermsize.js')
, EventEmitter = require('events').EventEmitter

function AppView(app){
EventEmitter.call(this)
this.app = app
this._currentTab = -1
this.cbs = {init: [], inputChar: []}
this.scrollOffset = 0
this.hScrollOffset = 0
this.logTextLines = []
this.init()
}
AppView.prototype = {
__proto__: EventEmitter.prototype,
init: function(){
charm.reset()
charm.erase('screen')
Expand All @@ -24,26 +26,21 @@ AppView.prototype = {
process.exit()
})
}.bind(this))
this.notify('init')
var checkTermSize = function(){
this.emit('init')
var self = this
;(function checkTermSize(){
getTermSize(function(cols, lines){
if (cols !== this.cols || lines !== this.lines){
this.cols = cols
this.lines = lines
charm.enableScroll(6, this.lines - 1)
this.renderAll()
if (cols !== self.cols || lines !== self.lines){
self.cols = cols
self.lines = lines
charm.enableScroll(6, self.lines - 1)
self.renderAll()
}
setTimeout(checkTermSize, 500)
}.bind(this))
}.bind(this)
checkTermSize()
})
}())
this.startRunningIndicator()
},
notify: function(event, args){
this.cbs[event].forEach(function(cb){
cb.apply(null, args)
})
},
failedBrowsers: function(){
return this.browsers().filter(function(b){
return b.results && b.results.failed > 0
Expand Down Expand Up @@ -85,9 +82,6 @@ AppView.prototype = {
+ 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2))
+ str + s.substr(0, l - t) : str;
},
on: function(event, cb){
this.cbs[event].push(cb)
},
onInputChar: function(buf){
//log.info('==buf')
//for (var i = 0, len = buf.length; i < len; i++)
Expand All @@ -108,7 +102,7 @@ AppView.prototype = {
this.scrollDown()
else if (key === 65) // up arrow
this.scrollUp()
this.notify('inputChar', [chr, i])
this.emit('inputChar', chr, i)
}catch(e){
log.error('In onInputChar: ' + e + '\n' + e.stack)
}
Expand Down Expand Up @@ -161,7 +155,7 @@ AppView.prototype = {
this.writeLine(1, 'Open the URL below in a browser to connect.')
charm.display('underscore')
var url = 'http://localhost:' +
this.app.server.config.port
this.app.config.port
charm
.position(0, 3)
.write(url)
Expand Down
10 changes: 5 additions & 5 deletions lib/browserclient.js
Expand Up @@ -33,16 +33,16 @@ BrowserClient.prototype = {
onTopLevelError: function(msg, url, line){
log.info('top-level error from browser')
this.topLevelError = msg + ' at ' + url + ', line ' + line
this.server.notify('browsers-changed')
this.server.emit('browsers-changed')
},
onBrowserLogin: function(browserName){
log.info('browser login: ' + browserName)
this.name = browserName
this.server.cleanUpConnections()
this.server.notify('browsers-changed')
this.server.emit('browsers-changed')
},
onTestsStart: function(){
this.server.notify('test-start')
this.server.emit('test-start')
},
onTestResult: function(result){
this.results.total++
Expand All @@ -51,11 +51,11 @@ BrowserClient.prototype = {
else
this.results.failed++
this.results.tests.push(result)
this.server.notify('test-result', result, this)
this.server.emit('test-result', result, this)
},
onAllTestResults: function(){
this.results.all = true
this.server.notify('all-test-results', this.results, this)
this.server.emit('all-test-results', this.results, this)
},
onDisconnect: function(){
log.info(this.name + ' disconnected')
Expand Down
63 changes: 30 additions & 33 deletions lib/dev_mode_app.js
Expand Up @@ -5,55 +5,52 @@ var Server = require('./server').Server
, child_process = require('child_process')
, AppView = require('./appviewcharm')
, Path = require('path')
, yaml = require('js-yaml')
, FileWatcher = require('./filewatcher')

function App(config){
this.config = config
this.fileWatchers = {}

log.info('phantomjs: ' + this.config.phantomjs)
if (config.config)
this.configFile = config.config

this.fileWatcher = new FileWatcher
this.fileWatcher.on('change', this.onFileChanged.bind(this))
this.fileWatcher.add(this.configFile)

this.configure(function(){
this.server = new Server(this)
this.server.on('browsers-changed', this.onBrowsersChanged.bind(this))
this.server.on('test-result', this.onTestResult.bind(this))
this.server.on('all-test-results', this.onAllTestResults.bind(this))
this.server.on('server-start', this.initView.bind(this))
}.bind(this))
this.server.on('file-requested', this.onFileRequested.bind(this))
})
}

App.prototype = {
configFile: 'testem.yml',
configure: function(callback){
var config = this.config
var finish = function(){
if (callback) callback(config)
}.bind(this)

if (config.f)
this.configFile = config.f
fs.stat(this.configFile, function(err, stat){
if (err){
finish()
}
else if (stat.isFile()){
fs.readFile(this.configFile, function(err, data){
if (!err){
var cfg = require('js-yaml')
.load(String(data))
for (var key in cfg)
config[key] = cfg[key]
}
finish()
})
var i = 1
if (!this.fileWatchers[this.configFile])
this.fileWatchers[this.configFile] =
fs.watch(this.configFile, debounce(function(event, filename){
this.configure(function(){
this.startTests()
}.bind(this))
}.bind(this), 1000, true))
, self = this
fs.readFile(self.configFile, function(err, data){
if (!err){
var cfg = yaml.load(String(data))
for (var key in cfg)
config[key] = cfg[key]
}
}.bind(this))
if (callback) callback.call(self)
})
},
onFileRequested: function(filepath){
this.fileWatcher.add(filepath)
},
onFileChanged: function(filepath){
if (filepath === this.configFile){
// config changed
this.configure(this.startTests.bind(this))
}else{
this.startTests()
}
},
startPhantomJS: function(){
var path = Path.dirname(__dirname) + '/assets/phantom.js'
Expand Down
50 changes: 32 additions & 18 deletions lib/filewatcher.js
Expand Up @@ -2,19 +2,40 @@ var fs = require('fs')
, glob = require('glob')
, log = require('util').debug
, path = require('path')
, EventEmitter = require('events').EventEmitter

function FileWatcher(){
this.cbs = {}
this.lastModTime = {}
EventEmitter.call(this)
this.fileInfo = {} // a map of file info, key by filepath
}

FileWatcher.prototype = {
__proto__: EventEmitter.prototype,
clear: function(){
for (var path in this.fileInfo){
var info = this.fileInfo[path]
info.watcher.close()
}
this.fileInfo = {}
this.emit('clear')
},
printWatched: function(){
for (var path in this.fileInfo){
console.log(path)
}
},
add: function(){
for (var i = 0, len = arguments.length; i < len; i++){
for (var i = 0; i < arguments.length; i++){
var glob = arguments[i]
this.watch(glob)
this.emit('add', 'glob')
}
},
getFileInfo: function(path){
if (!(path in this.fileInfo))
this.fileInfo[path] = {}
return this.fileInfo[path]
},
watch: function(globPattern){
var self = this
, dir = process.cwd()
Expand All @@ -24,33 +45,26 @@ FileWatcher.prototype = {
file = path.join(dir, file)
fs.stat(file, function(err, stats){
if (err) return
self.lastModTime[file] = +stats.mtime
fs.watch(file, function(evt){
var fileInfo = self.getFileInfo(file)
fileInfo.lastModTime = +stats.mtime
fileInfo.watcher = fs.watch(file, function(evt){
self.onAccess(evt, file)
})
})
})
})
},
onAccess: function(evt, filename){
var self = this
fs.stat(filename, function(err, stats){
if (err) return
var lastMTime = this.lastModTime[filename]
var fileInfo = self.getFileInfo(filename)
var lastMTime = fileInfo.lastModTime
if (!lastMTime || (stats.mtime > lastMTime)){
this.onChange(evt, filename)
this.lastModTime[filename] = +stats.mtime
self.emit('change', filename)
fileInfo.lastModTime = +stats.mtime
}
}.bind(this))
},
onChange: function(evt, filename){
this.cbs.change.forEach(function(cb){
cb('change', filename)
})
},
on: function(evt, cb){
if (!this.cbs[evt])
this.cbs[evt] = []
this.cbs[evt].push(cb)
}
}

Expand Down

0 comments on commit 188d09d

Please sign in to comment.