/test/repl.coffee

http://github.com/jashkenas/coffee-script · CoffeeScript · 140 lines · 101 code · 30 blank · 9 comment · 2 complexity · 89d9865ed6b30b5a41237767a92a997f MD5 · raw file

  1. return if global.testingBrowser
  2. os = require 'os'
  3. fs = require 'fs'
  4. path = require 'path'
  5. # REPL
  6. # ----
  7. Stream = require 'stream'
  8. class MockInputStream extends Stream
  9. constructor: ->
  10. super()
  11. @readable = true
  12. resume: ->
  13. emitLine: (val) ->
  14. @emit 'data', Buffer.from("#{val}\n")
  15. class MockOutputStream extends Stream
  16. constructor: ->
  17. super()
  18. @writable = true
  19. @written = []
  20. write: (data) ->
  21. # console.log 'output write', arguments
  22. @written.push data
  23. lastWrite: (fromEnd = -1) ->
  24. @written[@written.length - 1 + fromEnd].replace /\r?\n$/, ''
  25. # Create a dummy history file
  26. historyFile = path.join os.tmpdir(), '.coffee_history_test'
  27. fs.writeFileSync historyFile, '1 + 2\n'
  28. testRepl = (desc, fn) ->
  29. input = new MockInputStream
  30. output = new MockOutputStream
  31. repl = Repl.start {input, output, historyFile}
  32. test desc, -> fn input, output, repl
  33. ctrlV = { ctrl: true, name: 'v'}
  34. testRepl 'reads history file', (input, output, repl) ->
  35. input.emitLine repl.history[0]
  36. eq '3', output.lastWrite()
  37. testRepl "starts with coffee prompt", (input, output) ->
  38. eq 'coffee> ', output.lastWrite(0)
  39. testRepl "writes eval to output", (input, output) ->
  40. input.emitLine '1+1'
  41. eq '2', output.lastWrite()
  42. testRepl "comments are ignored", (input, output) ->
  43. input.emitLine '1 + 1 #foo'
  44. eq '2', output.lastWrite()
  45. testRepl "output in inspect mode", (input, output) ->
  46. input.emitLine '"1 + 1\\n"'
  47. eq "'1 + 1\\n'", output.lastWrite()
  48. testRepl "variables are saved", (input, output) ->
  49. input.emitLine "foo = 'foo'"
  50. input.emitLine 'foobar = "#{foo}bar"'
  51. eq "'foobar'", output.lastWrite()
  52. testRepl "empty command evaluates to undefined", (input, output) ->
  53. # A regression fixed in Node 5.11.0 broke the handling of pressing enter in
  54. # the Node REPL; see https://github.com/nodejs/node/pull/6090 and
  55. # https://github.com/jashkenas/coffeescript/issues/4502.
  56. # Just skip this test for versions of Node < 6.
  57. return if parseInt(process.versions.node.split('.')[0], 10) < 6
  58. input.emitLine ''
  59. eq 'undefined', output.lastWrite()
  60. testRepl "#4763: comment evaluates to undefined", (input, output) ->
  61. input.emitLine '# comment'
  62. eq 'undefined', output.lastWrite()
  63. testRepl "#4763: multiple comments evaluate to undefined", (input, output) ->
  64. input.emitLine '### a ### ### b ### # c'
  65. eq 'undefined', output.lastWrite()
  66. testRepl "ctrl-v toggles multiline prompt", (input, output) ->
  67. input.emit 'keypress', null, ctrlV
  68. eq '------> ', output.lastWrite(0)
  69. input.emit 'keypress', null, ctrlV
  70. eq 'coffee> ', output.lastWrite(0)
  71. testRepl "multiline continuation changes prompt", (input, output) ->
  72. input.emit 'keypress', null, ctrlV
  73. input.emitLine ''
  74. eq '....... ', output.lastWrite(0)
  75. testRepl "evaluates multiline", (input, output) ->
  76. # Stubs. Could assert on their use.
  77. output.cursorTo = (pos) ->
  78. output.clearLine = ->
  79. input.emit 'keypress', null, ctrlV
  80. input.emitLine 'do ->'
  81. input.emitLine ' 1 + 1'
  82. input.emit 'keypress', null, ctrlV
  83. eq '2', output.lastWrite()
  84. testRepl "variables in scope are preserved", (input, output) ->
  85. input.emitLine 'a = 1'
  86. input.emitLine 'do -> a = 2'
  87. input.emitLine 'a'
  88. eq '2', output.lastWrite()
  89. testRepl "existential assignment of previously declared variable", (input, output) ->
  90. input.emitLine 'a = null'
  91. input.emitLine 'a ?= 42'
  92. eq '42', output.lastWrite()
  93. testRepl "keeps running after runtime error", (input, output) ->
  94. input.emitLine 'a = b'
  95. input.emitLine 'a'
  96. eq 'undefined', output.lastWrite()
  97. testRepl "#4604: wraps an async function", (input, output) ->
  98. return unless try new Function 'async () => {}' # Feature detect support for async functions.
  99. input.emitLine 'await new Promise (resolve) -> setTimeout (-> resolve 33), 10'
  100. setTimeout ->
  101. eq '33', output.lastWrite()
  102. , 20
  103. testRepl "transpile REPL", (input, output) ->
  104. input.emitLine 'require("./test/importing/transpile_import").getSep()'
  105. eq "'#{path.sep.replace '\\', '\\\\'}'", output.lastWrite()
  106. process.on 'exit', ->
  107. try
  108. fs.unlinkSync historyFile
  109. catch exception # Already deleted, nothing else to do.