luca 0.9.65 → 0.9.76

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/CHANGELOG +30 -0
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +27 -0
  4. data/lib/luca/rails/version.rb +1 -1
  5. data/spec/components/controller_spec.coffee +58 -0
  6. data/spec/components/form_view_spec.coffee +4 -0
  7. data/spec/concerns/dom_helpers_spec.coffee +16 -0
  8. data/spec/{modules → concerns}/filterable_spec.coffee +0 -0
  9. data/spec/concerns/model_presenter_spec.coffee +31 -0
  10. data/spec/{modules → concerns}/paginatable_spec.coffee +0 -0
  11. data/spec/{modules → concerns}/state_model_spec.coffee +0 -0
  12. data/spec/concerns_spec.coffee +88 -0
  13. data/spec/core/container_spec.coffee +103 -6
  14. data/spec/core/field_spec.coffee +4 -0
  15. data/spec/core/model_spec.coffee +6 -1
  16. data/spec/define_spec.coffee +104 -7
  17. data/spec/framework_spec.coffee +30 -1
  18. data/spec/util_spec.coffee +24 -0
  19. data/src/components/application.coffee +62 -25
  20. data/src/components/base_toolbar.coffee +6 -4
  21. data/src/components/collection_loader_view.coffee +3 -1
  22. data/src/components/collection_view.coffee +36 -73
  23. data/src/components/controller.coffee +73 -35
  24. data/src/components/fields/button_field.coffee +20 -12
  25. data/src/components/fields/checkbox_array.coffee +8 -2
  26. data/src/components/fields/checkbox_field.coffee +18 -9
  27. data/src/components/fields/file_upload_field.coffee +5 -1
  28. data/src/components/fields/hidden_field.coffee +3 -1
  29. data/src/components/fields/label_field.coffee +4 -3
  30. data/src/components/fields/select_field.coffee +7 -8
  31. data/src/components/fields/text_area_field.coffee +3 -2
  32. data/src/components/fields/text_field.coffee +5 -4
  33. data/src/components/fields/type_ahead_field.coffee +4 -2
  34. data/src/components/form_button_toolbar.coffee +4 -1
  35. data/src/components/form_view.coffee +26 -24
  36. data/src/components/grid_view.coffee +3 -3
  37. data/src/components/multi_collection_view.coffee +6 -35
  38. data/src/components/pagination_control.coffee +1 -3
  39. data/src/components/router.coffee +2 -0
  40. data/src/components/table_view.coffee +7 -0
  41. data/src/concerns.coffee +70 -0
  42. data/src/{modules → concerns}/application_event_bindings.coffee +1 -1
  43. data/src/{modules → concerns}/collection_event_bindings.coffee +1 -1
  44. data/src/{modules → concerns}/deferrable.coffee +1 -1
  45. data/src/{modules → concerns}/dom_helpers.coffee +11 -2
  46. data/src/{modules → concerns}/enhanced_properties.coffee +1 -1
  47. data/src/{modules → concerns}/filterable.coffee +11 -11
  48. data/src/{modules → concerns}/grid_layout.coffee +1 -1
  49. data/src/{modules → concerns}/loadmaskable.coffee +1 -1
  50. data/src/{modules → concerns}/local_storage.coffee +0 -0
  51. data/src/{modules → concerns}/modal_view.coffee +1 -1
  52. data/src/concerns/model_presenter.coffee +23 -0
  53. data/src/{modules → concerns}/paginatable.coffee +9 -3
  54. data/src/concerns/query_collection_bindings.coffee +44 -0
  55. data/src/{modules → concerns}/state_model.coffee +1 -1
  56. data/src/{modules → concerns}/templating.coffee +1 -1
  57. data/src/containers/card_view.coffee +16 -9
  58. data/src/containers/tab_view.coffee +8 -11
  59. data/src/containers/viewport.coffee +3 -3
  60. data/src/core/collection.coffee +39 -28
  61. data/src/core/container.coffee +37 -15
  62. data/src/core/field.coffee +40 -39
  63. data/src/core/meta_data.coffee +93 -0
  64. data/src/core/model.coffee +18 -1
  65. data/src/core/registry.coffee +4 -3
  66. data/src/core/view.coffee +24 -30
  67. data/src/define.coffee +165 -79
  68. data/src/framework.coffee +97 -21
  69. data/src/index.coffee +4 -2
  70. data/src/managers/collection_manager.coffee +7 -3
  71. data/src/stylesheets/components/checkbox_array.scss +1 -1
  72. data/src/stylesheets/components/form_view.scss +5 -5
  73. data/src/stylesheets/components/viewport.scss +2 -1
  74. data/src/stylesheets/containers/container.scss +0 -5
  75. data/src/stylesheets/containers/tab_view.scss +5 -5
  76. data/src/templates/fields/text_area_field.jst.ejs +1 -1
  77. data/src/templates/fields/text_field.jst.ejs +1 -1
  78. data/src/util.coffee +47 -0
  79. data/vendor/assets/javascripts/luca-ui-full.js +1279 -494
  80. data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
  81. data/vendor/assets/javascripts/luca-ui-templates.js +2 -2
  82. data/vendor/assets/javascripts/luca-ui.js +1279 -494
  83. data/vendor/assets/javascripts/luca-ui.min.js +5 -4
  84. data/vendor/assets/stylesheets/luca-ui.css +15 -15
  85. metadata +27 -20
  86. data/spec/mixin_spec.coffee +0 -49
data/CHANGELOG CHANGED
@@ -184,3 +184,33 @@
184
184
  Previously required an element with a specific ID which made it harder to build extendable components
185
185
  with specific render targets
186
186
 
187
+ 0.9.66
188
+ - Luca.core.Container components can now be extended by subclasses by specifying an @extensions property.
189
+ @extensions work by applying the hash to the component in the same index'd position as that component
190
+ configuration in the superclass.
191
+ - Luca.components.CollectionView now has a @loadModels() method which resets the collection with the passed models.
192
+ - Added @componentMetaData() method which is going to replace the trickery done behind the scenes in Luca.extend
193
+ - Luca.config.autoApplyCssClassHierarchy if set to true, will add css class names to your luca components to make inheritance based styling easier.
194
+
195
+ 0.9.7
196
+ - Introduced publicInterface, publicConfiguration, privateInterface, and privateConfiguration as component registry methods.
197
+ These methods are intended to offer finer grain control over the component definition process for the purposes of building
198
+ our auto-generated documentation tool.
199
+ - Added Luca.concern support on Collection and Model
200
+ - Renaming 'mixin' and 'module' functionality to 'concern'
201
+ - Luca.concerns now follow the active support concern in spirit, with __included hooks, ClassMethods handling, etc
202
+ - Introducing an optional Concern for Luca.Model classes, called ModelPresenter.
203
+ - The callback argument passed to CardView activate, now gets called in the context of the activated component
204
+
205
+ 0.9.75
206
+ - Component registration is now beautifully readable and self documenting,
207
+ and flexible. Minimally only requires one call to Luca.register(). This allows you to be as descriptive as you like when defining a component, and does not require you to call any definition methods which do not make literary sense in your component description.
208
+ - Component definition now supports specifying class methods.
209
+ - Luca.initialize('Namespace') will setup a complete namespace for
210
+ your application, and give you a Namespace() method which works similar
211
+ to the Luca() helper.
212
+ - Added Luca.config.modelBootrstrap and Luca.config.baseParams as pointers
213
+ to either properties, or methods, which can be used to configure Luca.Collection behavior
214
+ - Luca.onReady is now the preferred way of launching the application.
215
+ - Added Luca.Application.routeTo, Luca.Application.controller
216
+ route building helpers
data/Gemfile CHANGED
@@ -15,4 +15,5 @@ group :test, :development do
15
15
  gem 'rb-fsevent', '>= 0.9.1'
16
16
  gem 'pry'
17
17
  gem 'guard-jasmine'
18
+ gem 'jasmine'
18
19
  end
data/Gemfile.lock CHANGED
@@ -1,6 +1,7 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ addressable (2.3.2)
4
5
  childprocess (0.3.1)
5
6
  ffi (~> 1.0.6)
6
7
  coderay (0.9.8)
@@ -8,6 +9,7 @@ GEM
8
9
  coffee-script-source
9
10
  execjs
10
11
  coffee-script-source (1.2.0)
12
+ diff-lcs (1.1.3)
11
13
  ejs (1.0.0)
12
14
  execjs (1.2.13)
13
15
  multi_json (~> 1.0)
@@ -28,6 +30,15 @@ GEM
28
30
  haml (3.1.4)
29
31
  hike (1.2.1)
30
32
  i18n (0.6.0)
33
+ jasmine (1.3.0)
34
+ jasmine-core (>= 1.3.0)
35
+ rack (~> 1.0)
36
+ rspec (>= 1.3.1)
37
+ selenium-webdriver (>= 0.1.3)
38
+ jasmine-core (1.3.0)
39
+ libwebsocket (0.1.7.1)
40
+ addressable
41
+ websocket
31
42
  method_source (0.6.7)
32
43
  ruby_parser (>= 2.3.1)
33
44
  multi_json (1.0.4)
@@ -41,9 +52,23 @@ GEM
41
52
  rack
42
53
  rake (0.9.2.2)
43
54
  rb-fsevent (0.9.1)
55
+ rspec (2.12.0)
56
+ rspec-core (~> 2.12.0)
57
+ rspec-expectations (~> 2.12.0)
58
+ rspec-mocks (~> 2.12.0)
59
+ rspec-core (2.12.0)
60
+ rspec-expectations (2.12.0)
61
+ diff-lcs (~> 1.1.3)
62
+ rspec-mocks (2.12.0)
44
63
  ruby_parser (2.3.1)
45
64
  sexp_processor (~> 3.0)
65
+ rubyzip (0.9.9)
46
66
  sass (3.1.12)
67
+ selenium-webdriver (2.26.0)
68
+ childprocess (>= 0.2.5)
69
+ libwebsocket (~> 0.1.3)
70
+ multi_json (~> 1.0)
71
+ rubyzip
47
72
  sexp_processor (3.0.9)
48
73
  sinatra (1.3.1)
49
74
  rack (~> 1.3, >= 1.3.4)
@@ -59,6 +84,7 @@ GEM
59
84
  uglifier (1.2.0)
60
85
  execjs (>= 0.3.0)
61
86
  multi_json (>= 1.0.2)
87
+ websocket (1.0.4)
62
88
 
63
89
  PLATFORMS
64
90
  ruby
@@ -70,6 +96,7 @@ DEPENDENCIES
70
96
  guard-jasmine
71
97
  guard-sprockets2
72
98
  haml
99
+ jasmine
73
100
  pry
74
101
  rake
75
102
  rb-fsevent (>= 0.9.1)
@@ -1,6 +1,6 @@
1
1
  module Luca
2
2
  module Rails
3
- VERSION = "0.9.65"
3
+ VERSION = "0.9.76"
4
4
  end
5
5
  end
6
6
 
@@ -0,0 +1,58 @@
1
+ describe 'The Controller Component', ->
2
+ beforeEach ->
3
+ controller = Luca.register 'Luca.components.SpecController'
4
+ controller.extends 'Luca.components.Controller'
5
+ controller.defines
6
+ name: "spec_controller"
7
+ defaultCard: 'one'
8
+ rootComponent: true
9
+ components:[
10
+ name: "one"
11
+ type: "controller"
12
+ components:[
13
+ name: "alpha"
14
+ ,
15
+ name: "bravo"
16
+ ]
17
+ ,
18
+ name: "two"
19
+ type: "controller"
20
+ components:[
21
+ name: "charlie"
22
+ ,
23
+ name: "delta"
24
+ ]
25
+ ,
26
+ name: "three"
27
+ type: "controller"
28
+ components:[
29
+ name: "echo"
30
+ ]
31
+ ,
32
+ name: "four"
33
+ type: "view"
34
+ ]
35
+
36
+ @controller = new Luca.components.SpecController().render()
37
+
38
+ it "should track the names of its pages", ->
39
+ names = @controller.sectionNames()
40
+ expect( names... ).toEqual 'one', 'two', 'three', 'four'
41
+
42
+ it "should track the names of its controllers", ->
43
+ names = _( @controller.controllers() ).pluck 'name'
44
+ expect( names... ).toEqual 'one', 'two', 'three'
45
+
46
+ it "should be stateful", ->
47
+ expect( @controller.state ).toBeDefined()
48
+
49
+ it "should track the active page", ->
50
+ @controller.navigate_to("two")
51
+ expect( @controller.activePage() ).toEqual 'two'
52
+
53
+ it "should define a controllerPath method on each page", ->
54
+ expect( @controller.activeComponent().controllerPath ).toBeDefined()
55
+
56
+ it "should know the controller path", ->
57
+ path = @controller.activeComponent().controllerPath()
58
+ expect( path... ).toEqual "spec_controller", "one"
@@ -47,6 +47,10 @@ describe 'The Form View', ->
47
47
  it "should create a form", ->
48
48
  expect( @form ).toBeDefined()
49
49
 
50
+ it "should have access to all of the fields", ->
51
+ @form.render()
52
+ expect( @form.getFields().length ).toEqual 6
53
+
50
54
  it "should load the model", ->
51
55
  @form.loadModel(@model)
52
56
  expect( @form.currentModel() ).toEqual @model
@@ -0,0 +1,16 @@
1
+ describe 'The DOM Helpers module', ->
2
+ describe "The Wrapping Helper", ->
3
+ it "should accept a space delimited list", ->
4
+ v = new Luca.View(wrapperClass: "class-one class-two")
5
+ expect( v.$el.parent().is(".class-one.class-two") ).toEqual(true)
6
+
7
+ describe "Auto Assigning Class Names", ->
8
+ it "should apply the class of the component all the way up its hierarchy", ->
9
+ c = new Luca.core.Container()
10
+ expect( c.$el.is(".luca-container") ).toBeTruthy()
11
+ expect( c.$el.is(".luca-panel") ).toBeTruthy()
12
+
13
+ it "should leave out backbone and luca view classes", ->
14
+ c = new Luca.core.Container()
15
+ expect( c.$el.is(".luca-view") ).not.toBeTruthy()
16
+ expect( c.$el.is(".backbone-view") ).not.toBeTruthy()
File without changes
@@ -0,0 +1,31 @@
1
+ describe 'The Presenter Mixin', ->
2
+ presenterModel = Luca.register("Luca.models.PresenterModel").extends("Luca.Model")
3
+ presenterModel.mixesIn("ModelPresenter")
4
+ presenterModel.defines
5
+ randomProperty: "chocolate"
6
+ fullName: ()->
7
+ @get("first_name") + ' ' + @get("last_name")
8
+ defaults:
9
+ first_name: "Jonathan"
10
+ last_name: "Soeder"
11
+
12
+ it "should respond to presentAs", ->
13
+ expect( Luca.models.PresenterModel::presentAs ).toBeDefined()
14
+
15
+ it "should define the presenter class methods on the model class", ->
16
+ expect( Luca.models.PresenterModel.registerPresenter ).toBeDefined()
17
+
18
+ it "should define the presenter class methods on the model class", ->
19
+ expect( Luca.models.PresenterModel.getPresenter ).toBeDefined()
20
+
21
+ it "should register a presenter format", ->
22
+ Luca.models.PresenterModel.registerPresenter "names", ["first_name", "last_name", "fullName"]
23
+ expect( Luca.models.PresenterModel.getPresenter("names") ).toBeDefined()
24
+
25
+ it "should present a model in the desired format", ->
26
+ model = new Luca.models.PresenterModel()
27
+ presented = model.presentAs('names')
28
+ expect( _.isObject(presented) ).toEqual true
29
+ expect( presented ).toBeDefined()
30
+ expect( _( presented ).keys()... ).toEqual "first_name", "last_name", "fullName"
31
+ expect( presented.fullName ).toEqual 'Jonathan Soeder'
File without changes
File without changes
@@ -0,0 +1,88 @@
1
+ describe 'The Concern System', ->
2
+
3
+ window.Luca ||= {}
4
+
5
+ Luca.concern.namespace 'Luca.test_concerns'
6
+
7
+ Luca.test_concerns =
8
+ CollectionMixin:
9
+ __initializer: ()->
10
+ @trigger "collection:mixin"
11
+ SecondMixin:
12
+ __included: ()->
13
+ window.secondMixinIncluded = true
14
+ __initializer: ()->
15
+ @trigger "second:mixin"
16
+ FirstMixin:
17
+ __initializer: ()->
18
+ @trigger "first:mixin"
19
+ __privateMethod: ()->
20
+ true
21
+ publicMethod: ()->
22
+ true
23
+
24
+ sampleView = Luca.register('Luca.components.FirstView')
25
+
26
+ sampleView.mixesIn 'FirstMixin'
27
+
28
+ sampleView.defines
29
+ sampleMethod: ()->
30
+ "sample"
31
+
32
+ secondView = Luca.register("Luca.components.SecondView")
33
+ secondView.extends 'Luca.components.FirstView'
34
+ secondView.mixesIn 'SecondMixin'
35
+ secondView.defines
36
+ version: 2
37
+
38
+ collection = Luca.register("Luca.components.MixinCollection")
39
+ collection.mixesIn "CollectionMixin"
40
+ collection.defines version: 2
41
+
42
+ model = Luca.register("Luca.components.MixinModel")
43
+ model.mixesIn "CollectionMixin"
44
+ model.defines version: 2
45
+
46
+ it "should work on models", ->
47
+ model = new Luca.components.MixinModel()
48
+ expect( model ).toHaveTriggered("collection:mixin")
49
+
50
+ it "should work on collections", ->
51
+ collection = new Luca.components.MixinCollection()
52
+ expect( collection ).toHaveTriggered("collection:mixin")
53
+
54
+ it "should work on views", ->
55
+ secondView = new Luca.components.SecondView
56
+ expect( secondView ).toHaveTriggered("second:mixin")
57
+
58
+ it "should omit methods prefixed with the double underscore", ->
59
+ sampleView = new Luca.components.FirstView
60
+ expect( sampleView.__privateMethod ).not.toBeDefined()
61
+
62
+
63
+ it "should extend the prototype with the concern definition", ->
64
+ sampleView = new Luca.components.FirstView
65
+ expect( sampleView.publicMethod ).toBeDefined()
66
+
67
+ it "should call the initializers up the prototype chain", ->
68
+ secondView = new Luca.components.SecondView
69
+ expect( secondView ).toHaveTriggered("first:mixin")
70
+ expect( secondView ).toHaveTriggered("second:mixin")
71
+
72
+ describe "Class Methods on the concern", ->
73
+ Luca.test_concerns.ExampleConcern =
74
+ instanceMethod: ()-> "instanceMethod"
75
+ classMethods:
76
+ classMethod: ()-> "classMethod"
77
+
78
+ v = Luca.register("Luca.components.ClassMethodView").mixesIn("ExampleConcern")
79
+
80
+ v.defines(version:1)
81
+
82
+ it "should distinguish between instance methods and class methods", ->
83
+ value = Luca.components.ClassMethodView::instanceMethod.call(@)
84
+ expect( value ).toEqual 'instanceMethod'
85
+
86
+ it "should distinguish between instance methods and class methods", ->
87
+ value = Luca.components.ClassMethodView.classMethod.call(@)
88
+ expect( value ).toEqual 'classMethod'
@@ -3,6 +3,13 @@ describe 'The Luca Container', ->
3
3
  c = @container = new Luca.core.Container
4
4
  defaults:
5
5
  defaultProperty: 'it_works'
6
+ extensions:[
7
+ extension: 1
8
+ ,
9
+ extension: 2
10
+ ,
11
+ extension: 3
12
+ ]
6
13
  components:[
7
14
  name: "component_one"
8
15
  ctype: "view"
@@ -47,6 +54,10 @@ describe 'The Luca Container', ->
47
54
  it "should create a getter function on the container", ->
48
55
  expect( @container.getOne().name ).toEqual 'component_one'
49
56
 
57
+ it "should apply extensions to the components", ->
58
+ expect( @container.getRoleOne().extension ).toEqual 1
59
+ expect( @container.getRoleTwo().extension ).toEqual 2
60
+
50
61
  it "should apply default properties to components", ->
51
62
  defaults = @container.selectByAttribute('defaultProperty','it_works')
52
63
  custom = @container.selectByAttribute('defaultProperty','oh_yeah')
@@ -85,6 +96,42 @@ describe 'The Luca Container', ->
85
96
  @container.eachComponent (c)-> c.spy()
86
97
  expect( Luca.cache("component_four").spy ).toHaveBeenCalled()
87
98
 
99
+ describe 'Component Inheritance and Customization', ->
100
+ it "should accept an array for extensions configuration and join on position/index", ->
101
+ container = new Luca.core.Container
102
+ extensions:[
103
+ undefined
104
+ ,
105
+ name: "custom_two"
106
+ ]
107
+ components:[
108
+ role: "component_one"
109
+ name: "component_one"
110
+ ,
111
+ role: "component_two"
112
+ name: "component_two"
113
+ ]
114
+
115
+ container.render()
116
+
117
+ expect( container.getComponentTwo().name ).toEqual "custom_two"
118
+
119
+ it "should accept an object for extensions configuration and join using role", ->
120
+ container = new Luca.core.Container
121
+ extensions:
122
+ component_one:
123
+ name: "custom_one"
124
+ components:[
125
+ role: "component_one"
126
+ name: "component_one"
127
+ ,
128
+ role: "component_two"
129
+ name: "component_two"
130
+ ]
131
+
132
+ container.render()
133
+
134
+ expect( container.getComponentOne().name ).toEqual "custom_one"
88
135
 
89
136
  describe 'Component Event Binding', ->
90
137
  beforeEach ->
@@ -97,19 +144,19 @@ describe 'Component Event Binding', ->
97
144
  "beta trigger:five" : "five"
98
145
 
99
146
  one: ()->
100
- @trigger "one"
147
+ @trigger "one"
101
148
 
102
149
  two: ()->
103
- @trigger "two"
150
+ @trigger "two"
104
151
 
105
152
  three: ()->
106
- @trigger "three"
153
+ @trigger "three"
107
154
 
108
155
  four: ()->
109
- @trigger "four"
156
+ @trigger "four"
110
157
 
111
158
  five: ()->
112
- @trigger "five"
159
+ @trigger "five"
113
160
 
114
161
  afterRender: ()->
115
162
  @getGamma().trigger("after:render:gamma")
@@ -146,7 +193,7 @@ describe 'Component Event Binding', ->
146
193
 
147
194
  it "should observe the right rendering order", ->
148
195
  expect( @container.getGamma() ).toHaveTriggered("after:render:gamma")
149
-
196
+
150
197
  it "should pick up events on nested components", ->
151
198
  @container.getBeta().trigger("trigger:five")
152
199
  expect( @container ).toHaveTriggered("five")
@@ -186,3 +233,53 @@ describe 'Component Event Binding', ->
186
233
  it "should accept component events with a component getter", ->
187
234
  @container.getAlphaComponent().trigger "trigger:three"
188
235
  expect(@container).toHaveTriggered("three")
236
+
237
+
238
+ describe 'Parent Container Tracking', ->
239
+ nestedContainer = Luca.register("Luca.components.NestedSpec")
240
+ nestedContainer.extends("Luca.core.Container")
241
+ nestedContainer.defines
242
+ name: "nested_container"
243
+ components:[
244
+ type: "container"
245
+ name: "one",
246
+ role: "one"
247
+ components:[
248
+ type: "container"
249
+ role: "two"
250
+ name: "two"
251
+ components:[
252
+ name: "three"
253
+ role: "three"
254
+ ]
255
+ ]
256
+ ]
257
+
258
+ it "should not have a parent unless created by a container", ->
259
+ nestedContainer = (new Luca.components.NestedSpec()).render()
260
+ expect( nestedContainer.getParent ).not.toBeDefined()
261
+
262
+ it "should know the root", ->
263
+ nestedContainer = (new Luca.components.NestedSpec()).render()
264
+ one = nestedContainer.getOne()
265
+ expect( one.getRootComponent().name ).toEqual 'nested_container'
266
+
267
+ it "should know the root", ->
268
+ nestedContainer = (new Luca.components.NestedSpec()).render()
269
+ two = nestedContainer.getTwo()
270
+ expect( two.getRootComponent().name ).toEqual 'nested_container'
271
+
272
+ it "should know its parent", ->
273
+ nestedContainer = (new Luca.components.NestedSpec()).render()
274
+ one = nestedContainer.getOne()
275
+ expect( one.getParent().name ).toEqual 'nested_container'
276
+
277
+ it "should know its parent", ->
278
+ nestedContainer = (new Luca.components.NestedSpec()).render()
279
+ two = nestedContainer.getTwo()
280
+ expect( two.getParent().name ).toEqual 'one'
281
+
282
+ it "should know its parent", ->
283
+ nestedContainer = (new Luca.components.NestedSpec()).render()
284
+ three = nestedContainer.getThree()
285
+ expect( three.getParent().name ).toEqual 'two'