REPL tests based on direct interaction with input and output stream. Includes multiline tests.

This commit is contained in:
Alon Salant 2013-01-21 10:02:04 -08:00
parent 537c5f4b70
commit 47bd05e9a0
4 changed files with 74 additions and 37 deletions

View File

@ -172,6 +172,7 @@ runTests = (CoffeeScript) ->
# Convenience aliases.
global.CoffeeScript = CoffeeScript
global.Repl = require './lib/coffee-script/repl'
# Our test helper function for delimiting different test cases.
global.test = (description, fn) ->

View File

@ -67,7 +67,7 @@
rli.prompt(true);
return;
}
if (!rli.line.match(/^\s*$/)) {
if (!((rli.line == null) || rli.line.match(/^\s*$/))) {
return;
}
multiline.enabled = !multiline.enabled;

View File

@ -54,7 +54,7 @@ addMultilineHandler = (repl) ->
rli.prompt true
return
# no-op unless the current line is empty
return unless rli.line.match /^\s*$/
return unless not rli.line? or rli.line.match /^\s*$/
# eval, print, loop
multiline.enabled = not multiline.enabled
rli.line = ''

View File

@ -1,46 +1,82 @@
# REPL
# ----
Stream = require 'stream'
# TODO: add more tests
{spawn} = require 'child_process'
PROMPT = 'coffee> '
class MockInputStream extends Stream
constructor: () ->
@readable = true
testOutput = (expected, actual) ->
eq expected, actual.slice(0, expected.length)
actual.substr expected.length
resume: ->
testCommands = (input, expectedOutput) ->
input = [input] if typeof input is 'string'
expectedOutput = [expectedOutput] if typeof expectedOutput in ['string', 'undefined']
output = ''
coffee = spawn 'bin/coffee'
input.push 'process.exit()'
emitLine: (val) ->
@emit 'data', new Buffer("#{val}\n")
coffee.stdout.on 'data', (data) ->
output += data.toString().replace(/\u001b\[\d{0,2}m/g, '')
coffee.stdin.write "#{input.shift()}\n"
class MockOutputStream extends Stream
constructor: () ->
@writable = true
@written = []
coffee.on 'exit', ->
output = testOutput PROMPT, output
while expectedOutput.length > 0
output = testOutput "#{expectedOutput.shift()}\n#{PROMPT}", output
eq '', output
write: (data) ->
#console.log 'output write', arguments
@written.push data
test "comments are ignored", ->
testCommands "1 + 1 #foo", "2"
lastWrite: (fromEnd=-1) ->
@written[@written.length - 1 + fromEnd].replace /\n$/, ''
test "output in inspect mode", ->
testCommands '"1 + 1\\n"', "'1 + 1\\n'"
testRepl = (desc, fn) ->
input = new MockInputStream()
output = new MockOutputStream()
Repl.start {input, output}
fn input, output
test "variables are saved", ->
input = [
"foo = 'foo'"
'foobar = "#{foo}bar"'
]
testCommands input, [
"'foo'"
"'foobar'"
]
assertEqual = (expected, value) ->
eq expected, value, "Expected '#{value}' to equal '#{expected}'"
test "empty command evaluates to undefined", ->
testCommands "", undefined
testRepl "starts with coffee prompt", (input, output) ->
assertEqual 'coffee> ', output.lastWrite(0)
testRepl "writes eval to output", (input, output) ->
input.emitLine '1+1'
assertEqual '2', output.lastWrite()
testRepl "comments are ignored", (input, output) ->
input.emitLine '1 + 1 #foo'
assertEqual '2', output.lastWrite()
testRepl "output in inspect mode", (input, output) ->
input.emitLine '"1 + 1\\n"'
assertEqual "'1 + 1\\n'", output.lastWrite()
testRepl "variables are saved", (input, output) ->
input.emitLine "foo = 'foo'"
input.emitLine 'foobar = "#{foo}bar"'
assertEqual "'foobar'", output.lastWrite()
testRepl "empty command evaluates to undefined", (input, output) ->
input.emitLine ''
assertEqual 'undefined', output.lastWrite()
ctrlV = { ctrl: true, name: 'v'}
testRepl "ctrl-v toggles multiline prompt", (input, output) ->
input.emit 'keypress', null, ctrlV
assertEqual '------> ', output.lastWrite(0)
input.emit 'keypress', null, ctrlV
assertEqual 'coffee> ', output.lastWrite(0)
testRepl "multiline continuation changes prompt", (input, output) ->
input.emit 'keypress', null, ctrlV
input.emitLine ''
assertEqual '....... ', output.lastWrite(0)
testRepl "evaluates multiline", (input, output) ->
# Stubs. Could assert on their use.
output.cursorTo = (pos) ->
output.clearLine = ->
input.emit 'keypress', null, ctrlV
input.emitLine '(->'
input.emitLine ' 1 + 1'
input.emitLine ')()'
input.emit 'keypress', null, ctrlV
assertEqual '2', output.lastWrite()