magic_lamp 0.9.0 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -75
  3. data/app/assets/javascripts/magic_lamp.js +2 -0
  4. data/app/assets/javascripts/magic_lamp/application.js +14 -0
  5. data/app/assets/javascripts/magic_lamp/boot.js +1 -0
  6. data/app/assets/javascripts/magic_lamp/genie.js +97 -0
  7. data/app/assets/javascripts/magic_lamp/magic_lamp.js +35 -0
  8. data/app/assets/stylesheets/magic_lamp/application.css +15 -0
  9. data/app/controllers/magic_lamp/application_controller.rb +4 -0
  10. data/app/controllers/magic_lamp/fixtures_controller.rb +35 -0
  11. data/app/helpers/magic_lamp/application_helper.rb +4 -0
  12. data/app/views/layouts/magic_lamp/application.html.erb +14 -0
  13. data/config/routes.rb +4 -0
  14. data/lib/magic_lamp.rb +83 -20
  15. data/lib/magic_lamp/engine.rb +9 -0
  16. data/lib/magic_lamp/fixture_creator.rb +2 -10
  17. data/lib/magic_lamp/render_catcher.rb +15 -0
  18. data/lib/magic_lamp/version.rb +1 -1
  19. data/lib/tasks/magic_lamp_tasks.rake +4 -0
  20. data/spec/controllers/magic_lamp/fixtures_controller_spec.rb +73 -0
  21. data/spec/dummy/app/views/orders/bar.html.erb +1 -0
  22. data/spec/dummy/config/application.rb +7 -1
  23. data/spec/dummy/config/environments/development.rb +1 -0
  24. data/spec/dummy/config/environments/production.rb +1 -2
  25. data/spec/dummy/config/initializers/assets.rb +8 -0
  26. data/spec/dummy/config/routes.rb +2 -54
  27. data/spec/dummy/config/secrets.yml +2 -2
  28. data/spec/dummy/db/development.sqlite3 +0 -0
  29. data/spec/dummy/db/migrate/{20140623002513_create_orders.rb → 20140801133550_create_orders.rb} +0 -0
  30. data/spec/dummy/db/schema.rb +1 -1
  31. data/spec/dummy/db/test.sqlite3 +0 -0
  32. data/spec/dummy/log/development.log +61270 -0
  33. data/spec/dummy/log/test.log +25531 -13475
  34. data/spec/dummy/spec/magical/magic_lamp.rb +12 -0
  35. data/spec/dummy/tmp/cache/assets/development/sprockets/05ecd34d23e110728a2f04ad35ec8834 +0 -0
  36. data/spec/dummy/tmp/cache/assets/development/sprockets/09bc89d8ac4ccacfcf2f4db466e7735f +0 -0
  37. data/spec/dummy/tmp/cache/assets/development/sprockets/0dc7d2551b4cf3f654b16902e208703c +0 -0
  38. data/spec/dummy/tmp/cache/assets/development/sprockets/18650d8ff9b0a83b32e55b58917ec791 +0 -0
  39. data/spec/dummy/tmp/cache/assets/development/sprockets/18a0c4b365b6a030c56ac85e8aa6bd6e +0 -0
  40. data/spec/dummy/tmp/cache/assets/development/sprockets/199574de4a8028cea9307b5e55d8f8be +0 -0
  41. data/spec/dummy/tmp/cache/assets/development/sprockets/1a894d48e2e8089537ae95e3798d49a2 +0 -0
  42. data/spec/dummy/tmp/cache/assets/development/sprockets/24591221375d773f23385966709a900b +0 -0
  43. data/spec/dummy/tmp/cache/assets/development/sprockets/2bd1588b3767c789462d94a5fd27df88 +0 -0
  44. data/spec/dummy/tmp/cache/assets/development/sprockets/2ccef21649a61deac2c84f622753b77b +0 -0
  45. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  46. data/spec/dummy/tmp/cache/assets/development/sprockets/38b32c335f7377670791219def8ce6d7 +0 -0
  47. data/spec/dummy/tmp/cache/assets/development/sprockets/38d787c2adf281dccb80274318dcf538 +0 -0
  48. data/spec/dummy/tmp/cache/assets/development/sprockets/3929ae7429411cd81cad5d5ed72b4912 +0 -0
  49. data/spec/dummy/tmp/cache/assets/development/sprockets/3c20b64b10f3325ed7f3b6695648fd8d +0 -0
  50. data/spec/dummy/tmp/cache/assets/development/sprockets/480053cec74750ba76acfd86f7ff1051 +0 -0
  51. data/spec/dummy/tmp/cache/assets/development/sprockets/5bbf09297502a156801e9c65f4bd3db7 +0 -0
  52. data/spec/dummy/tmp/cache/assets/development/sprockets/5ced43e55c875dddf3aca75fa148ca3e +0 -0
  53. data/spec/dummy/tmp/cache/assets/development/sprockets/6284ee4c2b5be7652a79edb6d4705cee +0 -0
  54. data/spec/dummy/tmp/cache/assets/development/sprockets/68b6ad376fe519ddaf9b84e87c2b077c +0 -0
  55. data/spec/dummy/tmp/cache/assets/development/sprockets/69080d1368510f3bcff08c323a5913a7 +0 -0
  56. data/spec/dummy/tmp/cache/assets/development/sprockets/6c1f143bdf6ffea1fb2fa7b967f9a437 +0 -0
  57. data/spec/dummy/tmp/cache/assets/development/sprockets/759e97d6d411bc4cef7055a778e1bef3 +0 -0
  58. data/spec/dummy/tmp/cache/assets/development/sprockets/7f7dcf7837dbb7f150b7364ad7920712 +0 -0
  59. data/spec/dummy/tmp/cache/assets/development/sprockets/86023efec2465a88617e5a47a38f1f55 +0 -0
  60. data/spec/dummy/tmp/cache/assets/development/sprockets/87e991f1f72e200b4bded1eb8871ee31 +0 -0
  61. data/spec/dummy/tmp/cache/assets/development/sprockets/88fe64427f1fff8e41ca8ad0170da88a +0 -0
  62. data/spec/dummy/tmp/cache/assets/development/sprockets/8d1d9aa6d95fc9c10dfc6e6d49778b2f +0 -0
  63. data/spec/dummy/tmp/cache/assets/development/sprockets/8ed4b4f20fb65446181984e6df7d7c9b +0 -0
  64. data/spec/dummy/tmp/cache/assets/development/sprockets/8f4a370f455559b7a209ecd758a3bb3d +0 -0
  65. data/spec/dummy/tmp/cache/assets/development/sprockets/96210dc070e479fcee862294afe5efc1 +0 -0
  66. data/spec/dummy/tmp/cache/assets/development/sprockets/972b6b0bb1fc0b1123077b4b2f4394bd +0 -0
  67. data/spec/dummy/tmp/cache/assets/development/sprockets/9825272284630c2926f661645205382a +0 -0
  68. data/spec/dummy/tmp/cache/assets/development/sprockets/9fdefd8efa47bbe9a18f1faff6252e95 +0 -0
  69. data/spec/dummy/tmp/cache/assets/development/sprockets/b212d365916d6c2f783d5d73ae451562 +0 -0
  70. data/spec/dummy/tmp/cache/assets/development/sprockets/b2a142b210c2cbfe4a58040684b3c33c +0 -0
  71. data/spec/dummy/tmp/cache/assets/development/sprockets/b458300066aff956f7af9a6d2ae99abc +0 -0
  72. data/spec/dummy/tmp/cache/assets/development/sprockets/b98b0da97c57b492a76eeb1d0faf80d7 +0 -0
  73. data/spec/dummy/tmp/cache/assets/development/sprockets/bceac3272b3e329aba55cb672fa18719 +0 -0
  74. data/spec/dummy/tmp/cache/assets/development/sprockets/bfa154e8a12acdbc85028ad8130d9043 +0 -0
  75. data/spec/dummy/tmp/cache/assets/development/sprockets/c5ff389414942659c1c69d2f4f32978c +0 -0
  76. data/spec/dummy/tmp/cache/assets/development/sprockets/cf573b52d944e8aea7f1dc03f9be9b2c +0 -0
  77. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  78. data/spec/dummy/tmp/cache/assets/development/sprockets/d42871ab2eba219379cd7aa9f993c575 +0 -0
  79. data/spec/dummy/tmp/cache/assets/development/sprockets/d98de652252dc6ae11b5b6db5588705b +0 -0
  80. data/spec/dummy/tmp/cache/assets/development/sprockets/db0cbe7314816ff20016f88d20dc5569 +0 -0
  81. data/spec/dummy/tmp/cache/assets/development/sprockets/ed02174e8f8230d1ff62c67e51f01576 +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sprockets/f0aa53eb377a5d7cc83657ef33b02d25 +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sprockets/f1ffba5065c7038b154a287981b34743 +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/f5d1b7d2ec1c89dc32cc982b43502dc8 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/f6256b2e4e609981d9eb420aae5bef46 +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/fd3d67db3401095777d74ebf3cb94a01 +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/fdc3718e0a84d340a897f87179d95c84 +0 -0
  89. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  90. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  91. data/spec/dummy/tmp/cache/assets/test/sprockets/2fdee9aa34e89b0182a7523c4484e5f6 +0 -0
  92. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  93. data/spec/dummy/tmp/cache/assets/test/sprockets/36a1fb9df9acb7490c5ac1284b2de56b +0 -0
  94. data/spec/dummy/tmp/cache/assets/test/sprockets/371bf96e99717688ed7313a0c53f4212 +0 -0
  95. data/spec/dummy/tmp/cache/assets/test/sprockets/6fc757c2c8329244ca95d6909865bbc2 +0 -0
  96. data/spec/dummy/tmp/cache/assets/test/sprockets/b78b6f63e1fe791ab77083cd45eb5105 +0 -0
  97. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  98. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  99. data/spec/dummy/tmp/cache/assets/test/sprockets/e4468469b981ba614a29626880137332 +0 -0
  100. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  101. data/spec/dummy/tmp/pids/server.pid +1 -0
  102. data/spec/javascripts/genie_spec.js +210 -0
  103. data/spec/javascripts/magic_lamp_spec.js +185 -0
  104. data/spec/javascripts/spec_helper.js +109 -0
  105. data/spec/javascripts/support/sinon-chai.js +126 -0
  106. data/spec/javascripts/support/underscore-1.6.js +1343 -0
  107. data/spec/lib/fixture_creator_spec.rb +6 -17
  108. data/spec/lib/magic_lamp_spec.rb +143 -56
  109. data/spec/lib/render_catcher_spec.rb +35 -0
  110. data/spec/rails_helper.rb +3 -13
  111. data/spec/spec_helper.rb +2 -3
  112. data/spec/teaspoon_env.rb +186 -0
  113. metadata +206 -15
  114. data/lib/tasks/magic_lamp_tasks.rb +0 -44
  115. data/spec/dummy/spec/magic_lamp.rb +0 -4
  116. data/spec/dummy/spec/magic_lamp/foo/foo_lamp.rb +0 -1
  117. data/spec/dummy/spec/magic_lamp/rake/rake_lamp.rb +0 -3
  118. data/spec/integration/integration_spec.rb +0 -21
  119. data/spec/tasks/magic_lamp_tasks_spec.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b6f5af7627ea40d33860f5a482bbe73568eccd7
4
- data.tar.gz: 719bca7fe3bf9ff43b9281bcab340ab067e25610
3
+ metadata.gz: 34dc16bf3efdeacd3b5b274d3aae3397b92c9245
4
+ data.tar.gz: bdf8b8529ece4f4148d3ed6f0ddb32f6dca4c9be
5
5
  SHA512:
6
- metadata.gz: 864494e38172878be15a56df14285d1f9704c6d7c4cdb7084a963614371ce5f43a06920f7ae11ad6a658cedc4d70574b26b89f6db5463699457aeed403d2d54d
7
- data.tar.gz: 28e5256c6730b96de2fd74c6ec94114f27878a97366c5b4e98cd011e10ad6e7c3f612c0aa9866c22c5bb4e3c2d82a5983c2ce8e48d4abf53ef2ac3f2764ce554
6
+ metadata.gz: 849734d6efead9d19a73bb6e08b41437de7c13d93da14e348e74296f3695f7c8a2a93e9eafdddfc496e991378ee6a999825c5368ab0b60455b9dc3880cb3c892
7
+ data.tar.gz: 712c6fd03a75c35f9b74ac746d96f15734437fdda425dd33921590a70a0ee43e30d82f359735f66f68f9c35678e60040e87dbc5b7bab9fbc7188bcc267ad5b69
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # MagicLamp
2
2
 
3
- MagicLamp ensures that if you change some markup in your templates that your JavaScript depends on that
4
- your tests will break. This is accomplished by generating fixture files from your actual templates just before running your JavaScript specs.
3
+ MagicLamp makes sure that your JavaScript tests break when you change a template your code depends on.
5
4
 
6
5
  ## Installation
7
6
 
@@ -16,89 +15,94 @@ And then execute:
16
15
  Or install it yourself as:
17
16
 
18
17
  $ gem install magic_lamp
18
+ ## Setup
19
+ ### Ruby side
20
+ Fixtures can be registered in any file that ends with `_lamp.rb` anywhere in your `spec` or `test` directory. You'll also need to mount MagicLamp in your `config/routes.rb` like so:
21
+ ```ruby
22
+ Rails.application.routes.draw do
23
+ # ...
24
+ mount MagicLamp::Genie, at: "/magic_lamp" if defined?(MagicLamp)
25
+ # ...
26
+ end
27
+ ```
28
+ ### JavaScript side
29
+ You can use any rails JavaScript spec runner that runs your application's server. If you're using [Teaspoon](https://github.com/modeset/teaspoon), simply add `//= require magic_lamp` to your `spec_helper.js`.
30
+
19
31
  ## Usage
20
- ### Basic usage
21
- In any file that ends in `_lamp.rb` in your `spec` or `test` directory:
32
+ A fixture can be registered like so:
22
33
  ```ruby
23
- MagicLamp.create_fixture("fixture_name", SomeController) do
24
-
25
- @instance_variable_your_template_depends_on = true
26
- # instance variables set in this block will be available to
27
- # the template you render. You also have access to the usual
28
- # controller methods and helpers here
29
- params[:foo] = "some param that's rendered for some reason"
30
-
31
- render :template_to_be_rendered
32
- # or
33
- # render partial: :partial_to_be_rendered
34
- # or
35
- # render partial: :foo, collection: [Foo.new, Foo.new, Foo.new]
36
- # or
37
- # pretty much anything you can normall do with render
34
+ MagicLamp.register_fixture do
35
+ @order = Order.new
36
+ render "orders/new"
38
37
  end
39
38
  ```
40
- Then if you ran:
41
-
42
- $ rake magic_lamp
43
- There would be a file called `fixture_name.html` containing the rendered template in `tmp/magic_lamp`.
44
- A more in depth example can be found below.
45
-
46
- ### Rake tasks
47
- The basic tasks are:
48
- * `rake magic_lamp:create_fixtures` - generates fixtures from `_lamp` files
49
- * `rake magic_lamp:clean` - deletes fixtures (by removing `tmp/magic_lamp`)
50
- * `rake magic_lamp` - alias for `rake magic_lamp:create_fixtures`
51
-
52
- Since you'll probably always want to run the create fixtures task before you run your JavaScript specs, MagicLamp comes with some convenience tasks that create your fixtures and then immediately run your JavaScript specs:
53
- * `rake magic_lamp:evergreen` - [Evergreen](https://github.com/abepetrillo/evergreen) integration (you'll need `gem "evergreen", require: "evergreen/rails"` for this to work)
54
- * `rake magic_lamp:jasmine` - [Jasmine Gem](https://github.com/pivotal/jasmine-gem) integration
55
- * `rake magic_lamp:jasmine_rails` - [JasmineRails](https://github.com/searls/jasmine-rails) integration
56
- * `rake magic_lamp:konacha` - [Konacha](https://github.com/jfirebaugh/konacha) integration
57
- * `rake magic_lamp:teaspoon` - [Teaspoon](https://github.com/modeset/teaspoon) integration
58
-
59
- ### In depth example
60
- Let"s assume we have `Order` model and `OrdersController` and that we want to test our JavaScript against the `views/orders/index.html.erb` that looks like this:
61
- ```html
62
- <ul class="orders">
63
- <% @orders.each do |order| %>
64
- <li>
65
- <%= order_name(order) %>
66
- </li>
67
- <% end %>
68
- </ul>
39
+ Then in your JavaScript specs you can do this:
40
+ ```js
41
+ MagicLamp.load('orders/new');
69
42
  ```
70
- The only dependencies in this template are `@orders` and the `order_name` helper method. So anywhere in `spec` or `test` we make a file that ends in `_lamp.rb` and write:
43
+ which will load the `"orders/new"` template into a `div` with an id of `magic-lamp`.
44
+
45
+ ### `MagicLamp#register_fixture`
71
46
 
47
+ `MagicLamp#register_fixture` requires a block. In this block you are scoped to a controller instance, so you have access to private and public controller methods and that any instance variables set in this block will be available
48
+ to the rendered template.
49
+
50
+ Optionally, `register_fixture` accepts a controller class and the name of the fixture. By default the controller class is `ApplicationController` and the name is what is passed to `render` (either the string, symbol passed in, or the value of the `partial` or `template` key if it's a hash). Here's a more explicit version of the example above:
51
+ ```ruby
52
+ MagicLamp.register_fixture(ApplicationController, "orders/new") do
53
+ @orders = [Order.new, Order.new, Order.new]
54
+ render "orders/new"
55
+ end
56
+ ```
57
+ Specifying the controller class gives you access to private methods in the block and helper methods in the template as well as not having to provide the full path to the template or partial.
58
+ ```ruby
59
+ MagicLamp.register_fixture(OrdersController) do
60
+ @order = some_private_method(Order.new)
61
+ render :index # index contains some special helper method
62
+ end
63
+ ```
64
+ In this example, the template will be registered as `"orders/index"`. The default name for a fixture is the controller's name followed by the template (unless it's the `ApplicationController`). If you have name collisions (or if you just want a more informative fixture name), simply specify the name as the second
65
+ argument to `register_fixture`.
72
66
  ```ruby
73
- MagicLamp.create_fixture("orders_index", OrdersController) do
74
- @orders = [
75
- Order.new(name: "foo", id: 1),
76
- Order.new(name: "bar", id: 2),
77
- Order.new(name: "baz", id: 3)
78
- ]
79
- render :index
67
+ MagicLamp.register_fixture(ApplicationController, "orders/new/with/errors") do
68
+ @order = Order.new
69
+ @errors = true
70
+ render :new
80
71
  end
81
72
  ```
82
- We want our fixture file to be named `orders_index.html`, so we pass in `"orders_index"` as the first argument. We pass in `OrdersController as the second argument because it's the only controller that knows about the `order_name` helper.
83
-
84
- So after we run `rake magic_lamp` we end up with a `orders_index.html` file in `tmp/magic_lamp` that looks like this:
85
- ```html
86
- <ul class="orders">
87
- <li>
88
- foo: 1
89
- </li>
90
- <li>
91
- bar: 2
92
- </li>
93
- <li>
94
- baz: 3
95
- </li>
96
- </ul>
73
+ Note: Only name your fixtures with characters that are the same in the url bar of a browser as they are everywhere else.
74
+
75
+ Also note: blocks using the default name will be executed twice (that's part of the magic required to get sweet defaults). If you don't want that to happen, just name your fixture.
76
+
77
+ ### controller#render
78
+ Everything in the block you pass to `register_fixture` is scoped to an instance of the specified controller or the `ApplicationController`. `render` behaves normally for the most part. The only magic here is to set the `layout` option to default to `false`. Aside from that though, it's normal:
79
+ ```ruby
80
+ MagicLamp.register_fixture(OrdersController) do
81
+ render partial: "order",
82
+ locals: { foo: "bar" },
83
+ collection: [Order.new, Order.new, Order.new]
84
+ # etc.
85
+ end
97
86
  ```
87
+ ### MagicLamp JS
88
+ To load a fixture simply call `MagicLamp.load('fixture/name');`. To clear out the fixture `div`, call `MagicLamp.clean();`. If you call `MagicLamp.globalize();`, you be able to call `load` and `clean` right on `window`. If you'd like to preload all of your fixtures so you can stub network requests or something, just call `MagicLamp.preload();`.
89
+
90
+ The `id` of the `div` MagicLamp creates to hold the fixtures can be specified by setting `MagicLamp.id`.
91
+
92
+ ### Errors
93
+ If there are any errors rendering your templates, MagicLamp will log them to the server log and throw an error in JavaScript. If the error in the JavaScript doesn't make the source of the problem clear, please check the server log. If that doesn't help, open up a `rails console` and enter `MagicLamp.load_lamp_files` and see if there are any errors. If not, try calling `MagicLamp.generate_all_fixtures` and seeing if the error shows up then.
94
+
95
+ ### Sweet aliases
96
+ `MagicLamp#register_fixture` is aliased as `rub` and `wish`. On the JavaScript side of things, `load` is `rub` and `wish`. `preload` is `massage` and `wishForMoreWishes`. `clean` is `polish`.
97
+
98
98
  ## Contributing
99
99
 
100
100
  1. Fork it
101
- 2. Create your feature branch (`git checkout -b my-new-feature`)
102
- 3. Commit your changes (`git commit -am 'Add some feature'`)
103
- 4. Push to the branch (`git push origin my-new-feature`)
104
- 5. Create new Pull Request
101
+ 2. Clone it locally
102
+ 3. `bundle install`
103
+ 4. Run the `./bootstrap` script
104
+ 5. Run the specs with `rake`
105
+ 6. Create your feature branch (`git checkout -b my-new-feature`)
106
+ 7. Commit your changes (`git commit -am 'Add some feature'`)
107
+ 8. Push to the branch (`git push origin my-new-feature`)
108
+ 9. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ //= require magic_lamp/application
2
+ //= require magic_lamp/boot
@@ -0,0 +1,14 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require magic_lamp/magic_lamp
14
+ //= require magic_lamp/genie
@@ -0,0 +1 @@
1
+ MagicLamp.initialize();
@@ -0,0 +1,97 @@
1
+ (function(global) {
2
+
3
+ function Genie() {
4
+ this.cache = {};
5
+ this.cacheOnly = false;
6
+ this.namespace = MagicLamp;
7
+ }
8
+
9
+ Genie.prototype = {
10
+
11
+ load: function(path) {
12
+ var fixture = this.cache[path];
13
+ this.createFixtureContainer();
14
+
15
+ if (!fixture && this.cacheOnly) {
16
+ throw new Error('The fixture "' + path + '" was not preloaded. Is the fixture registered? Such a bummer.');
17
+ } else if (!fixture) {
18
+ var xhr = this.xhrRequest(getPath() + '/' + path);
19
+ this.cache[path] = fixture = xhr.responseText;
20
+ }
21
+
22
+ this.fixtureContainer.innerHTML = fixture;
23
+ this.appendFixtureContainer();
24
+ },
25
+
26
+ preload: function() {
27
+ this.cacheOnly = true;
28
+ var xhr = this.xhrRequest(getPath());
29
+ var json = JSON.parse(xhr.responseText);
30
+ this.cache = json;
31
+ },
32
+
33
+ createFixtureContainer: function() {
34
+ var div = document.createElement('div');
35
+ div.setAttribute('id', this.namespace.id || 'magic-lamp');
36
+ this.fixtureContainer = div;
37
+ },
38
+
39
+ appendFixtureContainer: function() {
40
+ document.body.appendChild(this.fixtureContainer);
41
+ },
42
+
43
+ removeFixtureContainer: function() {
44
+ remove(this.fixtureContainer);
45
+ this.fixtureContainer = undefined;
46
+ },
47
+
48
+ handleError: function(errorMessage) {
49
+ throw new Error(errorMessage);
50
+ },
51
+
52
+ xhrRequest: function(path) {
53
+ var xhr = newXhr();
54
+
55
+ xhr.open('GET', path, false);
56
+ xhr.send();
57
+
58
+ if (xhr.status !== 200) {
59
+ this.handleError(xhr.responseText);
60
+ }
61
+ return xhr;
62
+ }
63
+ };
64
+
65
+ // private
66
+
67
+ function getPath() {
68
+ return MagicLamp.path || '/magic_lamp';
69
+ }
70
+
71
+ function remove(node) {
72
+ node.parentNode.removeChild(node);
73
+ }
74
+
75
+ function newXhr() {
76
+ var xhr;
77
+ if (window.XMLHttpRequest) { // Mozilla, Safari, ...
78
+ xhr = new XMLHttpRequest();
79
+ } else if (window.ActiveXObject) { // IE
80
+ try {
81
+ xhr = new ActiveXObject('Msxml2.XMLHTTP');
82
+ } catch (error) {
83
+ try {
84
+ xhr = new ActiveXObject('Microsoft.XMLHTTP');
85
+ } catch (e) {
86
+ // let it go
87
+ }
88
+ }
89
+ }
90
+ if (!xhr) {
91
+ throw('Unable to make request');
92
+ }
93
+ return xhr;
94
+ }
95
+
96
+ MagicLamp.Genie = Genie;
97
+ })(this);
@@ -0,0 +1,35 @@
1
+ var MagicLamp = {
2
+
3
+ initialize: function() {
4
+ this.genie = new this.Genie();
5
+ },
6
+
7
+ globalize: function() {
8
+ var context = this;
9
+ window.load = function(path) {
10
+ context.load(path);
11
+ };
12
+ window.clean = function() {
13
+ context.clean();
14
+ };
15
+ },
16
+
17
+ load: function() {
18
+ this.genie.load.apply(this.genie, arguments);
19
+ },
20
+
21
+ preload: function() {
22
+ this.genie.preload.apply(this.genie, arguments);
23
+ },
24
+
25
+ clean: function() {
26
+ this.genie.removeFixtureContainer();
27
+ }
28
+ };
29
+
30
+ // aliases
31
+ MagicLamp.rub = MagicLamp.load;
32
+ MagicLamp.wish = MagicLamp.load;
33
+ MagicLamp.massage = MagicLamp.preload;
34
+ MagicLamp.wishForMoreWishes = MagicLamp.preload;
35
+ MagicLamp.polish = MagicLamp.clean;
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module MagicLamp
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,35 @@
1
+ module MagicLamp
2
+ class FixturesController < ApplicationController
3
+ ERRORS = [
4
+ "ArgumentError",
5
+ "MagicLamp::AlreadyRegisteredFixtureError",
6
+ "MagicLamp::AmbiguousFixtureNameError",
7
+ "MagicLamp::UnregisteredFixtureError"
8
+ ]
9
+
10
+ rescue_from(*ERRORS) do |exception, message = exception.message|
11
+ error_message_with_bactrace = parse_error(exception, message)
12
+ logger.error(error_message_with_bactrace)
13
+ render text: message, status: 500
14
+ end
15
+
16
+ def show
17
+ namespace.load_lamp_files
18
+ render text: namespace.generate_fixture(params[:name])
19
+ end
20
+
21
+ def index
22
+ render json: namespace.generate_all_fixtures
23
+ end
24
+
25
+ private
26
+
27
+ def parse_error(exception, message)
28
+ ([message] + exception.backtrace).join("\n\s\s\s\s")
29
+ end
30
+
31
+ def namespace
32
+ MagicLamp
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ module MagicLamp
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>MagicLamp</title>
5
+ <%= stylesheet_link_tag "magic_lamp/application", media: "all" %>
6
+ <%= javascript_include_tag "magic_lamp/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ MagicLamp::Engine.routes.draw do
2
+ root to: "fixtures#index"
3
+ get "/*name", controller: :fixtures, action: :show
4
+ end
data/lib/magic_lamp.rb CHANGED
@@ -1,50 +1,113 @@
1
+ require "magic_lamp/fixture_creator"
2
+ require "magic_lamp/render_catcher"
3
+ require "magic_lamp/engine"
4
+
1
5
  module MagicLamp
2
6
  LAMP = "_lamp"
3
- MAGIC_LAMP = "magic#{LAMP}"
4
7
  SPEC = "spec"
5
8
  STARS = "**"
6
9
  TEST = "test"
7
- TMP = "tmp"
8
- TMP_PATH = [TMP, MAGIC_LAMP]
10
+ Genie = Engine
11
+
12
+ class AmbiguousFixtureNameError < StandardError
13
+ end
14
+
15
+ class UnregisteredFixtureError < StandardError
16
+ end
17
+
18
+ class AlreadyRegisteredFixtureError < StandardError
19
+ end
9
20
 
10
21
  class << self
22
+ attr_accessor :registered_fixtures
23
+
11
24
  def path
12
25
  Rails.root.join(directory_path)
13
26
  end
14
27
 
15
- def create_fixture(fixture_name, controller_class, &block)
16
- FixtureCreator.new.create_fixture(fixture_name, controller_class, &block)
28
+ def register_fixture(controller_class = ::ApplicationController, fixture_name = nil, &block)
29
+ if block.nil?
30
+ raise ArgumentError, "MagicLamp#register_fixture requires a block"
31
+ end
32
+
33
+ if fixture_name.nil?
34
+ fixture_name = default_fixture_name(controller_class, fixture_name, block)
35
+ end
36
+
37
+ if registered?(fixture_name)
38
+ raise AlreadyRegisteredFixtureError, "a fixture called '#{fixture_name}' has already been registered"
39
+ end
40
+
41
+ registered_fixtures[fixture_name] = [controller_class, block]
17
42
  end
18
43
 
19
- def load_lamp_files
20
- create_tmp_directory
21
- require_all(Dir[path.join(STARS, "*#{LAMP}.rb")])
44
+ alias_method :rub, :register_fixture
45
+ alias_method :wish, :register_fixture
46
+
47
+ def registered?(fixture_name)
48
+ registered_fixtures.key?(fixture_name)
22
49
  end
23
50
 
24
- def tmp_path
25
- Rails.root.join(*TMP_PATH)
51
+ def load_lamp_files
52
+ self.registered_fixtures = {}
53
+ load_all(Dir[path.join(STARS, "*#{LAMP}.rb")])
26
54
  end
27
55
 
28
- def create_tmp_directory
29
- FileUtils.mkdir_p(tmp_path)
56
+ def generate_fixture(fixture_name)
57
+ unless registered?(fixture_name)
58
+ raise UnregisteredFixtureError, "'#{fixture_name}' is not a registered fixture"
59
+ end
60
+ controller_class, block = registered_fixtures[fixture_name]
61
+ FixtureCreator.new.generate_template(controller_class, &block)
30
62
  end
31
63
 
32
- def remove_tmp_directory
33
- FileUtils.rm_rf(tmp_path)
64
+ def generate_all_fixtures
65
+ load_lamp_files
66
+ registered_fixtures.keys.each_with_object({}) do |fixture_name, fixtures|
67
+ fixtures[fixture_name] = generate_fixture(fixture_name)
68
+ end
34
69
  end
35
70
 
36
71
  private
37
72
 
73
+ def default_fixture_name(controller_class, fixture_name, block)
74
+ first_arg = first_render_arg(block)
75
+ fixture_name = template_name(first_arg).to_s
76
+ if fixture_name.blank?
77
+ raise AmbiguousFixtureNameError, "Unable to infer fixture name"
78
+ end
79
+ fixture_name = prepend_controller_name(fixture_name, controller_class)
80
+ fixture_name
81
+ end
82
+
83
+ def first_render_arg(block)
84
+ render_catcher = RenderCatcher.new
85
+ render_catcher.first_render_argument(&block)
86
+ end
87
+
88
+ def template_name(render_arg)
89
+ if render_arg.is_a?(Hash)
90
+ render_arg[:template] || render_arg[:partial]
91
+ else
92
+ render_arg
93
+ end
94
+ end
95
+
96
+ def prepend_controller_name(fixture_name, controller_class)
97
+ controller_name = controller_class.controller_name
98
+ if controller_name == "application"
99
+ fixture_name
100
+ else
101
+ "#{controller_name}/#{fixture_name}"
102
+ end
103
+ end
104
+
38
105
  def directory_path
39
106
  Dir.exist?(Rails.root.join(SPEC)) ? SPEC : TEST
40
107
  end
41
108
 
42
- def require_all(files)
43
- files.each { |file| require file }
109
+ def load_all(files)
110
+ files.each { |file| load file }
44
111
  end
45
112
  end
46
113
  end
47
-
48
- require "fileutils"
49
- require "magic_lamp/fixture_creator"
50
- require "tasks/magic_lamp_tasks"