updated app

This commit is contained in:
2012-05-30 23:00:06 -04:00
parent 6a753904b7
commit da6ad88d48
5545 changed files with 1101709 additions and 60 deletions

View File

@@ -0,0 +1,99 @@
{expect, calls} = require 'racer/test/util'
EventDispatcher = require '../lib/EventDispatcher'
describe 'EventDispatcher', ->
# Names must be a valid object key
name1 = 'test event'
name2 = 89
# Listeners can be anything that is representable in plain JSON
listener1 = [1, 2, 'qu"a"il', "'", {arr: ['x', 'y']}]
listener2 = 0
listener3 = 'stuff'
listener4 = true
# The second and third parameters sent to trigger are simply passed through
# to the callback function. They can be anything.
value1 = 'test value'
options1 = {option: 4}
it 'should work without callbacks', ->
dispatcher = new EventDispatcher
dispatcher.bind name1, listener1
dispatcher.trigger name1, value1, options1
it 'calls onTrigger', calls 2, (done) ->
dispatcher = new EventDispatcher
onTrigger: (name, listener, value, options) ->
expect(listener).to.eql listener1
expect(value).to.equal value1
expect(options).to.equal options1
done()
dispatcher.bind name1, listener1
dispatcher.trigger name1, value1, options1
dispatcher.trigger name1, value1, options1
it 'calls onTrigger without listener', calls 2, (done) ->
dispatcher = new EventDispatcher
onTrigger: (name, listener, value, options) ->
expect(listener).to.equal undefined
expect(value).to.equal value1
expect(options).to.equal options1
done()
dispatcher.bind name1
dispatcher.trigger name1, value1, options1
dispatcher.trigger name1, value1, options1
it 'calls onTrigger for multiple listeners', calls 1, (done) ->
counts = {all: 0}
beforeExit = ->
expect(counts[listener2]).to.equal 1
expect(counts[listener3]).to.equal 3
expect(counts[listener4]).to.equal 1
done()
dispatcher = new EventDispatcher
onTrigger: (name, listener, value, options) ->
counts[listener] = (counts[listener] || 0) + 1
expect(value).to.equal value1
expect(options).to.equal options1
beforeExit() if ++counts.all == 5
dispatcher.bind name1, listener2
dispatcher.bind name1, listener3
dispatcher.bind name1, listener4
dispatcher.bind name2, listener3
dispatcher.trigger name1, value1, options1
dispatcher.trigger name2, value1, options1
dispatcher.trigger name2, value1, options1
it 'test EventDispatcher remove listener after failed trigger', calls 1, (done) ->
dispatcher = new EventDispatcher
onTrigger: ->
done()
return false
dispatcher.bind name1
dispatcher.trigger name1
dispatcher.trigger name1
it 'test EventDispatcher do not trigger twice after double bind', calls 1, (done) ->
dispatcher = new EventDispatcher onTrigger: done
dispatcher.bind name1, listener1
dispatcher.bind name1, listener1
dispatcher.trigger name1
it 'test EventDispatcher bind callback', calls 3, (done) ->
dispatcher = new EventDispatcher
onTrigger: (name, listener, value, options) ->
expect(listener).to.eql listener1
expect(value).to.equal value1
expect(options).to.equal options1
done()
onBind: (name, listener) ->
expect(name).to.equal name1
expect(listener).to.eql listener1
done()
dispatcher.bind name1, listener1
dispatcher.trigger name1, value1, options1
dispatcher.trigger name1, value1, options1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,130 @@
{expect, calls} = require 'racer/test/util'
{DetachedModel: Model} = require './mocks'
View = require '../lib/View.server'
describe 'App HTML components', ->
it 'supports void components', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2>"'
view.make 'test2', 'hi'
expect(view.get 'test').to.equal 'say "hi"'
it 'supports literal attributes', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2 message="Howdy">" or "<app:test2>"'
view.make 'test2', '''
{{{#if message}}}
{{{message}}}
{{{else}}}
Yo
{{{/}}}
'''
expect(view.get 'test').to.equal 'say "Howdy" or "Yo"'
it 'macro attributes are case-insensitive', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2 messAGE="Howdy">" or "<app:test2>"'
view.make 'test2', '''
{{{#if messAGE}}}
{{{message}}}
{{{else}}}
Yo
{{{/}}}
'''
expect(view.get 'test').to.equal 'say "Howdy" or "Yo"'
it 'supports boolean and numerical attributes', ->
view = new View
view._init new Model
view.make 'test', '<app:test2 show="true"> / <app:test2 num="-4.5"> / <app:test2 show="false">'
view.make 'test2', '''
{{{#if show}}}
Hi
{{{else if equal(num, -4.5)}}}
Got it
{{{else}}}
Nada
{{{/}}}
'''
expect(view.get 'test').to.equal 'Hi / Got it / Nada'
it 'supports variable attributes', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2 message="{{myMessage}}">"'
view.make 'test2', '''
{{{#if message}}}
{{{message}}}
{{{else}}}
Yo
{{{/}}}
'''
expect(view.get 'test').to.equal 'say "Yo"'
expect(view.get 'test', myMessage: 'Heyo').to.equal 'say "Heyo"'
it 'supports variable object attributes', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2 message="{{myMessage}}">"'
view.make 'test2', '''
{{{#with message}}}
{{text}}
{{{/}}}
'''
expect(view.get 'test', myMessage: {text: 'Heyo'}).to.equal 'say "Heyo"'
it 'supports dot syntax for properties of variable object attributes', ->
view = new View
view._init new Model
view.make 'test', 'say "<app:test2 message="{{myMessage}}">"'
view.make 'test2', '''
{{{message.text}}}
'''
expect(view.get 'test', myMessage: {text: 'Heyo'}).to.equal 'say "Heyo"'
it 'supports bound attributes', ->
view = new View
model = new Model
view._init model
view.make 'test', 'say "<app:test2 message="{myMessage}">"'
view.make 'test2', '''
{{{#if message}}}
{{{message}}}
{{{else}}}
Yo
{{{/}}}
'''
model.set 'myMessage', 'Heyo'
expect(view.get 'test').to.equal 'say "<!--$0--><!--$1-->Heyo<!--$$1--><!--$$0-->"'
it 'supports bound attributes as element attributes', ->
view = new View
model = new Model
view._init model
view.make 'test', 'say "<app:test2 message="{myMessage}">"'
view.make 'test2', '''
<div title={{{message}}}></div>
'''
model.set 'myMessage', 'Heyo'
expect(view.get 'test').to.equal 'say "<div id=$0 title=Heyo></div>"'
it 'supports nonvoid components', ->
view = new View
view._init new Model
view.make 'test', '<ul><app:test2><b>Hi!</b></app:test2></ul>'
view.make 'test2', '<li>{{{content}}}</li>', {nonvoid: null}
expect(view.get 'test').to.equal '<ul><li><b>Hi!</b></li></ul>'

376
first-project/node_modules/derby/test/View.mocha.coffee generated vendored Normal file
View File

@@ -0,0 +1,376 @@
{expect, calls} = require 'racer/test/util'
{DetachedModel: Model, ResMock} = require './mocks'
View = require '../lib/View.server'
describe 'View', ->
it 'supports view.render with no defined views', ->
view = new View
res = new ResMock
res.onEnd = (html) ->
expect(html).to.match /^<!DOCTYPE html><meta charset=utf-8><title>.*<\/title><script>.*<\/script><script.*><\/script>$/
view.render res
it 'supports rendering a string literal view', ->
view = new View
view._init new Model
view.make 'test', """
<style>
body {
margin:
0
}
</style>
"""
# String views should have line breaks and leading whitespace removed
expect(view.get 'test').to.eql '<style>body {margin: 0}</style>'
it 'doctypes and conditional comments are maintained', ->
view = new View
view._init new Model
view.make 'test', """
<!DOCTYPE html>
<!-- This comment is removed -->
<title></title>
<!--[if gt IE 6]>
IE greater than 6
<![endif]-->
<!--[if !IE]> -->
Not IE
<!-- <![endif]-->
"""
expect(view.get 'test').to.eql '<!DOCTYPE html>' +
'<title></title>' +
'<!--[if gt IE 6]>\n' +
'IE greater than 6\n' +
'<![endif]-->' +
'<!--[if !IE]> -->Not IE<!-- <![endif]-->'
it 'supports substituting variables into text', ->
view = new View
model = new Model
view._init model
view.make 'test', '''
{{connected}}{{canConnect}} {{nada}}
<p>
{{name}}
</p>
<p>
{{age}} - {{height}} - {{weight}}
</p>
'''
ctx =
connected: false
weight: '165 lbs'
nada: null
model.set 'name', 'John'
model.set 'age', 22
model.set 'height', '6 ft 2 in'
model.set 'weight', '175 lbs'
expected = 'falsetrue ' +
'<p>John</p>' +
'<p>22 - 6 ft 2 in - 165 lbs</p>'
expect(view.get 'test', ctx).to.equal expected
it 'supports binding variables in text', ->
view = new View
model = new Model
view._init model
view.make 'test', '''
{connected}{canConnect} {nada}
<p>
{name}
</p>
<p>
{age} - {height} - {weight}
</p>
'''
ctx =
connected: false
weight: '165 lbs'
nada: null
model.set 'name', 'John'
model.set 'age', 22
model.set 'height', '6 ft 2 in'
model.set 'weight', '175 lbs'
expect(view.get 'test', ctx).to.equal '<!--$0-->false<!--$$0--><!--$1-->true<!--$$1--> <!--$2--><!--$$2-->' +
'<p id=$3>John</p>' +
'<p><!--$4-->22<!--$$4--> - <!--$5-->6 ft 2 in<!--$$5--> - <!--$6-->165 lbs<!--$$6--></p>'
it 'supports HTML escaping', ->
view = new View
model = new Model
view._init model
# Attribute values are escaped regardless of placeholder type
# Ampersands are escaped at the end of a replacement even when not
# required, because it is sometimes needed depending on the following item
template = '''<input value="{unescaped html}"> {html}x{unescaped html}'''
value = '<b id="hey">&Hi! & x& </b>&'
expected =
'<input id=$0 value="<b id=&quot;hey&quot;>&amp;Hi! & x& </b>&amp;"> ' +
'<!--$1-->&lt;b id="hey">&amp;Hi! & x& &lt;/b>&amp;<!--$$1-->x' +
'<!--$2--><b id="hey">&Hi! & x& </b>&<!--$$2-->'
view.make 'test1', template
expect(view.get 'test1', html: value).to.eql expected
view._idCount = 0
model.set 'html', value
expect(view.get 'test1').to.eql expected
view.make 'test2',
'<p a={{a}} b={{b}} c={{c}} d={{d}} e={{e}} f={{f}} g={{g}} h={{h}} i>'
expect(view.get 'test2',
{a: '"', b: "'", c: '<', d: '>', e: '=', f: ' ', g: '', h: null}
).to.eql '<p a=&quot; b="\'" c="<" d=">" e="=" f=" " g="" h="" i>'
it 'supports HTML entity unescaping in string partials', ->
view = new View
model = new Model
view._init model
view.make 'title', '{{unescaped name}} - stuff'
ctx = name: 'Cr&egrave;me Br&ucirc;l&eacute;e'
expect(view.get 'title$s', ctx).to.eql 'Crème Brûlée - stuff'
it 'supports conditional blocks in text', ->
view = new View
model = new Model
view._init model
view.make 'literal',
'{{#if show}}Yep{{else}}Nope{{/}}{{#if show}} Yes!{{/}} {{#unless show}}No{{/}}'
view.make 'bound',
'{#if show}Yep{else}Nope{/}{#if show} Yes!{/} {#unless show}No{/}'
literalTruthy = 'Yep Yes! '
literalFalsey = 'Nope No'
modelTruthy = '<!--$0-->Yep<!--$$0--><!--$1--> Yes!<!--$$1--> <!--$2--><!--$$2-->'
modelFalsey = '<!--$0-->Nope<!--$$0--><!--$1--><!--$$1--> <!--$2-->No<!--$$2-->'
expect(view.get 'literal', show: true).to.eql literalTruthy
expect(view.get 'literal', show: 1).to.eql literalTruthy
expect(view.get 'literal', show: 'x').to.eql literalTruthy
expect(view.get 'literal', show: {}).to.eql literalTruthy
expect(view.get 'literal', show: [1]).to.eql literalTruthy
expect(view.get 'literal', show: false).to.eql literalFalsey
expect(view.get 'literal', show: undefined).to.eql literalFalsey
expect(view.get 'literal', show: null).to.eql literalFalsey
expect(view.get 'literal', show: 0).to.eql literalFalsey
expect(view.get 'literal', show: '').to.eql literalFalsey
expect(view.get 'literal', show: []).to.eql literalFalsey
expect(view.get 'literal').to.eql literalFalsey
# No parameter assumes it is a model path that is undefined
view._idCount = 0
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', true
expect(view.get 'bound').to.eql modelTruthy
view._idCount = 0
model.set 'show', 1
expect(view.get 'bound').to.eql modelTruthy
view._idCount = 0
model.set 'show', 'x'
expect(view.get 'bound').to.eql modelTruthy
view._idCount = 0
model.set 'show', {}
expect(view.get 'bound').to.eql modelTruthy
view._idCount = 0
model.set 'show', false
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', undefined
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', null
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', 0
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', ''
expect(view.get 'bound').to.eql modelFalsey
view._idCount = 0
model.set 'show', []
expect(view.get 'bound').to.eql modelFalsey
it 'supports else if conditionals', ->
view = new View
view._init new Model
view.make 'test', """
{{#if equal('red', value)}}
1
{{else if equal('red', value)}}
2
{{else if equal('green', value)}}
3
{{else}}
4
{{/}}
"""
expect(view.get 'test', value: 'red').to.equal '1'
expect(view.get 'test', value: 'green').to.equal '3'
expect(view.get 'test', value: 'blue').to.equal '4'
expect(view.get 'test').to.equal '4'
it 'supports unless then else conditionals', ->
view = new View
view._init new Model
view.make 'test', """
{{#unless value}}
1
{{else}}
2
{{/}}
"""
expect(view.get 'test', value: true).to.equal '2'
expect(view.get 'test', value: false).to.equal '1'
it 'supports lists in text', ->
view = new View
view._init new Model
template = """
<ul>
{{#each arr}}
<li>{{name}}
{{else}}
<li>Nothing to see
{{/}}
</ul>
"""
view.make 'test', template
expect(view.get 'test', arr: [])
.to.eql '<ul><li>Nothing to see</ul>'
view.make 'test', template
expect(view.get 'test', arr: [{name: 'stuff'}, {name: 'more'}])
.to.eql '<ul><li>stuff<li>more</ul>'
it 'supports boolean attributes', ->
view = new View
view._init new Model
view.make 'test', '<input disabled={maybe}>'
expect(view.get 'test').to.equal '<input id=$0>'
expect(view.get 'test', maybe: false).to.equal '<input id=$1>'
expect(view.get 'test', maybe: true).to.equal '<input id=$2 disabled>'
it 'supports paths containing dots for ctx object items', ->
view = new View
view._init new Model
view.make 'test', '<b>{{user.name}}</b>'
ctx = user: {name: 'John'}
expect(view.get 'test', ctx).to.equal '<b>John</b>'
it 'supports relative paths for ctx object items', ->
view = new View
view._init new Model
view.make 'test', '{{#if user}}<b>{{.name}}</b>{{/}}'
ctx = user: {name: 'John'}
expect(view.get 'test', ctx).to.equal '<b>John</b>'
it 'supports Arrays containing non-objects from ctx', ->
view = new View
view._init new Model
view.make 'test1', '{{#each bools}}<b>{{this}}</b>{{/}}'
view.make 'test2', '{{#each bools as :value}}<b>{{:value}}</b>{{/}}'
ctx = bools: [true, false, true]
expect(view.get 'test1', ctx).to.equal '<b>true</b><b>false</b><b>true</b>'
expect(view.get 'test2', ctx).to.equal '<b>true</b><b>false</b><b>true</b>'
it 'supports view helper functions', ->
view = new View
model = new Model
view._init model
view.fn 'lower', (s) -> s.toLowerCase()
view.make 'test', '''{{lower('HI')}} {lower( "HI" )}'''
expect(view.get 'test').to.equal 'hi <!--$0-->hi<!--$$0-->'
view.fn 'sum', (a, b) -> a + b
view.make 'test', '{{sum(4, 9)}}'
expect(view.get 'test').to.equal '13'
view._idCount = 0
view.make 'test', '{equal(1, sum(-5, 6))}'
expect(view.get 'test').to.equal '<!--$0-->true<!--$$0-->'
view._idCount = 0
view.make 'test', '{unescaped equal(sum(-5, 6), 1)}'
expect(view.get 'test').to.equal '<!--$0-->true<!--$$0-->'
view.make 'test', '{{sum(4, count)}}'
expect(view.get 'test', {count: 7}).to.equal '11'
model.set 'count', 13
expect(view.get 'test').to.equal '17'
view._idCount = 0
view.make 'test', '''
<select>
{{#each items}}
<option selected="{{equal(this, current)}}">{{this}}
{{/}}
</select>
'''
expect(view.get 'test',
items: ['a', 'b', 'c']
current: 'c'
).to.equal '<select id=$0><option>a<option>b<option selected>c</select>'
view.fn 'positive', (num) -> num >= 0
view.make 'test', '''
{{#each nums as :num}}
{{#if positive(:num)}}
{{:num}},
{{/}}
{{/}}
'''
expect(view.get 'test', {nums: [-4, 8, 0, 2.3, -9]}).to.equal '8,0,2.3,'
it 'supports x-no-minify', ->
view = new View
view._init new Model
view.make 'test', '''
<script type="x-test" x-no-minify>
Some text
And a new line
</script>
'''
expect(view.get 'test').to.equal '''
<script type=x-test>
Some text
And a new line
</script>
'''

View File

@@ -0,0 +1,28 @@
{expect, calls} = require 'racer/test/util'
fs = require "fs"
files = require "../lib/files"
derby = require "../lib/derby"
describe 'files.css', ->
it "should compile less", (done) ->
derby.configure "all", ->
derby.set "styles", "less"
expected = fs.readFileSync __dirname + "/fixtures/styles/app/expected.less.css", 'utf8'
files.css __dirname + "/fixtures", "app", false, (err, contents) ->
# nextTick because stylus.render catches assertions
process.nextTick ->
expect(contents).to.equal expected
done()
it "should compile stylus", (done) ->
derby.configure "all", ->
derby.set "styles", ["stylus"]
expected = fs.readFileSync __dirname + "/fixtures/styles/app/expected.styl.css", 'utf8'
files.css __dirname + "/fixtures", "app", false, (err, contents) ->
process.nextTick ->
expect(contents).to.equal expected
done()

View File

@@ -0,0 +1,2 @@
<box:>
<div class="box"></div>

View File

@@ -0,0 +1,2 @@
<button: nonvoid>
<button>{{{content}}}</button>

View File

@@ -0,0 +1,15 @@
<dropdown:>
<!-- a :self path alias is automatically created per component -->
<!-- x-as can be used to pass a reference to an element to the script -->
<div x-as="container" class="{#if :self.open}open{/}">
<button x-bind="click: clickButton">{{{value}}} <i class="caret"></i></button>
<menu x-bind="click: clickMenu">
{{{#each list}}}
{{#if separator}}
<hr>
{{else}}
<li>{{text}}</li>
{{/}}
{{{/}}}
</menu>
</div>

View File

@@ -0,0 +1,29 @@
// Components must export a create function
// Components are passed a scoped model underneath _$component.{uid}
exports.create = function(self, dom, elements) {
var container = elements.container
, open = self.at('open')
// Listeners added inside of a component should be automatically
// removed when the instance is removed from the DOM
dom.addListener(document.documentElement, 'click', function(e) {
if (!container.contains(e.target)) {
open.set(false)
}
})
exports.clickButton = function() {
open.set(!open.get())
}
exports.clickMenu = function(e, el) {
var item = model.at(el)
, value = item.get()
open.set(false)
if (value.text == null) return
self.set('value', value.text)
self.set('index', +item.leaf())
}
}

View File

@@ -0,0 +1,11 @@
var scripts = {
dropdown: require('./dropdown')
}
module.exports = plugin
plugin.decorate = 'derby'
plugin.useWith = {server: true, browser: true}
function plugin(derby, options) {
derby.createLibrary(module, scripts, options)
}

View File

@@ -0,0 +1,3 @@
#less {
color: #4d926f;
}

View File

@@ -0,0 +1,3 @@
#styl {
color: #4d926f;
}

View File

@@ -0,0 +1,5 @@
@color: #4D926F;
#less {
color: @color;
}

View File

@@ -0,0 +1,2 @@
#styl
color #4D926F

View File

@@ -0,0 +1,32 @@
{expect} = require 'racer/test/util'
{DetachedModel: Model} = require './mocks'
derby = require '../lib/derby'
View = require '../lib/View.server'
ui = require './fixtures/components/ui'
describe 'Component libraries', ->
derby.use ui
it 'supports void components from libraries', ->
view = new View(derby._libraries)
view._init new Model
view.make 'test', 'give me a <ui:box>'
expect(view.get 'test').to.equal 'give me a <div class=box></div>'
it 'supports non-void components from libraries', ->
view = new View(derby._libraries)
view._init new Model
view.make 'test', 'give me a <ui:button>Click</ui:button>'
expect(view.get 'test').to.equal 'give me a <button>Click</button>'
it 'supports rendering full components from libraries', ->
view = new View(derby._libraries)
view._init new Model
view.make 'test', 'give me a <ui:dropdown>'
expect(view.get 'test').to.equal 'give me a <div id=$0 class="">' +
'<button id=$1> <i class=caret></i></button>' +
'<menu id=$2></menu></div>'

6
first-project/node_modules/derby/test/mocha.opts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
--colors
--reporter spec
--timeout 1200
--growl
--debug
--compilers coffee:coffee-script

21
first-project/node_modules/derby/test/mocks.coffee generated vendored Normal file
View File

@@ -0,0 +1,21 @@
{Model} = require('racer').protected
DetachedModel = exports.DetachedModel = ->
Model.apply this, arguments
return
DetachedModel:: =
__proto__: Model::
_commit: ->
ResMock = exports.ResMock = ->
@html = ''
return
ResMock:: =
getHeader: ->
setHeader: ->
write: write = (value) ->
@html += value
send: write
end: (value) ->
write value
@onEnd? @html