Skip to content

Commit

Permalink
Merge pull request #4378 from GeoffreyBooth/fix-browser-tests
Browse files Browse the repository at this point in the history
Fix browser tests
  • Loading branch information
jashkenas authored Nov 30, 2016
2 parents ac26360 + d99ae0e commit 5588658
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 221 deletions.
168 changes: 95 additions & 73 deletions Cakefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,60 +45,6 @@ run = (args, cb) ->
log = (message, color, explanation) ->
console.log color + message + reset + ' ' + (explanation or '')

codeFor = ->
counter = 0
hljs = require 'highlight.js'
hljs.configure classPrefix: ''
(file, executable = false, showLoad = true) ->
counter++
return unless fs.existsSync "docs/v#{majorVersion}/examples/#{file}.js"
cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
js = fs.readFileSync "docs/v#{majorVersion}/examples/#{file}.js", 'utf-8'
js = js.replace /^\/\/ generated.*?\n/i, ''

cshtml = "<pre><code>#{hljs.highlight('coffeescript', cs).value}</code></pre>"
# Temporary fix until highlight.js adds support for newer CoffeeScript keywords
# Added in https://github.com/isagalaev/highlight.js/pull/1357, awaiting release
if file in ['generator_iteration', 'generators', 'modules']
cshtml = cshtml.replace /(yield|import|export|from|as|default) /g, '<span class="keyword">$1</span> '
jshtml = "<pre><code>#{hljs.highlight('javascript', js).value}</code></pre>"
append = if executable is yes then '' else "alert(#{executable});"
if executable and executable isnt yes
cs.replace /(\S)\s*\Z/m, "$1\n\nalert #{executable}"
run = if executable is true then 'run' else "run: #{executable}"
name = "example#{counter}"
script = "<script>window.#{name} = #{JSON.stringify cs}</script>"
load = if showLoad then "<div class='minibutton load' onclick='javascript: loadConsole(#{name});'>load</div>" else ''
button = if executable then "<div class='minibutton ok' onclick='javascript: #{js};#{append}'>#{run}</div>" else ''
"<div class='code'>#{cshtml}#{jshtml}#{script}#{load}#{button}<br class='clear' /></div>"

monthNames = [
'January'
'February'
'March'
'April'
'May'
'June'
'July'
'August'
'September'
'October'
'November'
'December'
]

formatDate = (date) ->
date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) ->
"#{monthNames[$2 - 1]} #{+$3}, #{$1}"

releaseHeader = (date, version, prevVersion) -> """
<div class="anchor" id="#{version}"></div>
<b class="header">
#{prevVersion and "<a href=\"https://github.com/jashkenas/coffeescript/compare/#{prevVersion}...#{version}\">#{version}</a>" or version}
<span class="timestamp"> &mdash; <time datetime="#{date}">#{formatDate date}</time></span>
</b>
"""

option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`'

task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) ->
Expand Down Expand Up @@ -137,7 +83,7 @@ task 'build:full', 'rebuild the source twice, and run the tests', ->


task 'build:parser', 'rebuild the Jison parser (run build first)', ->
helpers.extend global, require('util')
helpers.extend global, require 'util'
require 'jison'
parser = require('./lib/coffee-script/grammar').parser
fs.writeFileSync 'lib/coffee-script/parser.js', parser.generate()
Expand Down Expand Up @@ -182,13 +128,93 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',


task 'doc:site', 'watch and continually rebuild the documentation for the website', ->
# Helpers
codeFor = ->
counter = 0
hljs = require 'highlight.js'
hljs.configure classPrefix: ''
(file, executable = false, showLoad = true) ->
counter++
return unless fs.existsSync "docs/v#{majorVersion}/examples/#{file}.js"
cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
js = fs.readFileSync "docs/v#{majorVersion}/examples/#{file}.js", 'utf-8'
js = js.replace /^\/\/ generated.*?\n/i, ''

cshtml = "<pre><code>#{hljs.highlight('coffeescript', cs).value}</code></pre>"
# Temporary fix until highlight.js adds support for newer CoffeeScript keywords
# Added in https://github.com/isagalaev/highlight.js/pull/1357, awaiting release
if file in ['generator_iteration', 'generators', 'modules']
cshtml = cshtml.replace /(yield|import|export|from|as|default) /g, '<span class="keyword">$1</span> '
jshtml = "<pre><code>#{hljs.highlight('javascript', js).value}</code></pre>"
append = if executable is yes then '' else "alert(#{executable});"
if executable and executable isnt yes
cs.replace /(\S)\s*\Z/m, "$1\n\nalert #{executable}"
run = if executable is true then 'run' else "run: #{executable}"
name = "example#{counter}"
script = "<script>window.#{name} = #{JSON.stringify cs}</script>"
load = if showLoad then "<div class='minibutton load' onclick='javascript: loadConsole(#{name});'>load</div>" else ''
button = if executable then "<div class='minibutton ok' onclick='javascript: #{js};#{append}'>#{run}</div>" else ''
"<div class='code'>#{cshtml}#{jshtml}#{script}#{load}#{button}<br class='clear' /></div>"

monthNames = [
'January'
'February'
'March'
'April'
'May'
'June'
'July'
'August'
'September'
'October'
'November'
'December'
]

formatDate = (date) ->
date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) ->
"#{monthNames[$2 - 1]} #{+$3}, #{$1}"

releaseHeader = (date, version, prevVersion) -> """
<div class="anchor" id="#{version}"></div>
<b class="header">
#{prevVersion and "<a href=\"https://github.com/jashkenas/coffeescript/compare/#{prevVersion}...#{version}\">#{version}</a>" or version}
<span class="timestamp"> &mdash; <time datetime="#{date}">#{formatDate date}</time></span>
</b>
"""

testHelpers = fs.readFileSync('test/support/helpers.coffee', 'utf-8').replace /exports\./g, '@'

testsInScriptBlocks = ->
output = ''
excludedTestFiles = ['error_messages.coffee']
for filename in fs.readdirSync 'test'
continue if filename in excludedTestFiles

if filename.indexOf('.coffee') isnt -1
type = 'coffeescript'
else if filename.indexOf('.litcoffee') isnt -1
type = 'literate-coffeescript'
else
continue

# Set the type to text/x-coffeescript or text/x-literate-coffeescript
# to prevent the browser compiler from automatically running the script
output += """
<script type="text/x-#{type}" class="test" id="#{filename.split('.')[0]}">
#{fs.readFileSync "test/#{filename}", 'utf-8'}
</script>\n
"""
output

# Task
examplesSourceFolder = 'documentation/examples'
examplesOutputFolder = "docs/v#{majorVersion}/examples"
fs.mkdirSync examplesOutputFolder unless fs.existsSync examplesOutputFolder
do renderExamples = ->
execSync "bin/coffee -bc -o #{examplesOutputFolder} #{examplesSourceFolder}/*.coffee"

indexFile = 'documentation/index.html.js'
indexFile = 'documentation/index.html'
do renderIndex = ->
render = _.template fs.readFileSync(indexFile, 'utf-8')
output = render
Expand All @@ -198,10 +224,22 @@ task 'doc:site', 'watch and continually rebuild the documentation for the websit
fs.writeFileSync "docs/v#{majorVersion}/index.html", output
log 'compiled', green, "#{indexFile} → docs/v#{majorVersion}/index.html"

testFile = 'documentation/test.html'
do renderTest = ->
render = _.template fs.readFileSync(testFile, 'utf-8')
output = render
testHelpers: testHelpers
tests: testsInScriptBlocks()
majorVersion: majorVersion
fs.writeFileSync "docs/v#{majorVersion}/test.html", output
log 'compiled', green, "#{testFile} → docs/v#{majorVersion}/test.html"

fs.watch examplesSourceFolder, interval: 200, ->
renderExamples()
renderIndex()
fs.watch indexFile, interval: 200, renderIndex
fs.watch testFile, interval: 200, renderTest
fs.watch 'test', interval: 200, renderTest
log 'watching...' , green


Expand Down Expand Up @@ -258,23 +296,7 @@ runTests = (CoffeeScript) ->
description: description if description?
source: fn.toString() if fn.toString?

# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
egal = (a, b) ->
if a is b
a isnt 0 or 1/a is 1/b
else
a isnt a and b isnt b

# A recursive functional equivalence helper; uses egal for testing equivalence.
arrayEgal = (a, b) ->
if egal a, b then yes
else if a instanceof Array and b instanceof Array
return no unless a.length is b.length
return no for el, idx in a when not arrayEgal el, b[idx]
yes

global.eq = (a, b, msg) -> ok egal(a, b), msg ? "Expected #{a} to equal #{b}"
global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg ? "Expected #{a} to deep equal #{b}"
helpers.extend global, require './test/support/helpers'

# When all the tests have run, collect and print errors.
# If a stacktrace is available, output the compiled function source.
Expand Down
1 change: 0 additions & 1 deletion docs/current

This file was deleted.

File renamed without changes.
114 changes: 114 additions & 0 deletions documentation/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>CoffeeScript Test Suite</title>
<script src="browser-compiler/coffee-script.js"></script>
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
<style>
body, pre {
font-family: Consolas, Menlo, Monaco, monospace;
}
body {
margin: 1em;
}
h1 {
font-size: 1.3em;
}
div {
margin: 0.6em;
}
.good {
color: #22b24c
}
.bad {
color: #eb6864
}
.subtle {
font-size: 0.7em;
color: #999999
}
</style>
</head>
<body>

<h1>CoffeeScript Test Suite</h1>

<pre id="stdout"></pre>

<script type="text/coffeescript">
@testingBrowser = yes
@global = window
stdout = document.getElementById 'stdout'
start = new Date
success = total = done = failed = 0

say = (msg, className) ->
div = document.createElement 'div'
div.className = className if className?
div.appendChild document.createTextNode msg
stdout.appendChild div
msg

@test = (description, fn) ->
++total
try
fn.call(fn)
++success
catch exception
say "#{description}:", 'bad'
say fn.toString(), 'subtle' if fn.toString?
say exception, 'bad'
console.error exception

@ok = (good, msg = 'Error') ->
throw Error msg unless good

# Polyfill Node assert's fail
@fail = ->
ok no

# Polyfill Node assert's deepEqual with Underscore's isEqual
@deepEqual = (a, b) ->
ok _.isEqual(a, b), "Expected #{JSON.stringify a} to deep equal #{JSON.stringify b}"

<%= testHelpers %>

@doesNotThrow = (fn) ->
fn()
ok yes

@throws = (fun, err, msg) ->
try
fun()
catch e
if err
if typeof err is 'function' and e instanceof err # Handle comparing exceptions
ok yes
else
eq e, err
else
ok yes
return
ok no


# Run the tests
for test in document.getElementsByClassName 'test'
say '\u2714 ' + test.id
options = {}
options.literate = yes if test.type is 'text/x-literate-coffeescript'
CoffeeScript.run test.innerHTML, options

# Finish up
yay = success is total and not failed
sec = (new Date - start) / 1000
msg = "passed #{success} tests in #{ sec.toFixed 2 } seconds"
msg = "failed #{ total - success } tests and #{msg}" unless yay
say msg, (if yay then 'good' else 'bad')
</script>

<%= tests %>

</body>
</html>
Loading

0 comments on commit 5588658

Please sign in to comment.