Can't find haml-js templates during Jasmine test run - javascript

I'm trying to test some backbone.js views using Jasmine (via jasmine-headless-webkit). Everything is working well, except that my haml-js templates aren't accessible under test.
The following code in my view works fine:
render: =>
html = JST['views/avia_view_template']()
$(#el).html(html)
... but when it's run as part of a Jasmine spec I get the following failure:
ReferenceError: Can't find variable: JST in /home/duncan/avia/app/assets/javascripts/views/avia_view.js.coffee
I suspect I'm doing something wrong in jasmine.yml. I've explicitly included the template file it still fails:
src_files:
- "vendor/**/*.{js,coffee}"
- "lib/**/*.{js,coffee}"
- app/assets/javascripts/application.js
- app/assets/javascripts/avia.js
- app/assets/javascripts/jquery-1.6.4.js
- app/assets/javascripts/underscore.js
- app/assets/javascripts/backbone.js
- app/assets/javascripts/jquery.jqGrid.min.js
- app/assets/javascripts/views/avia_view_template.jst.hamljs
- app/assets/javascripts/views/avia_view.js.coffee
Perhaps I'm just taking the wrong approach here ... should I be using Jasmine to stub & mock out the calls to JST and jQuery? A strictly unit-testing approach says I should, in which case the lack of template access is a non-issue.
Any tips - either on my approach to testing, or the specific JST failure, would be greatly appreciated.

No need to stub, you just need to set up your asset paths correctly. In order to take advantage of the Sprockets integration in 0.8.0 and above, the best way to set up your jasmine.yml file would be like this:
src_dir: app/assets/javascripts
asset_paths:
- lib/assets/javascripts
src_files:
- "**/*"
This will set up Sprockets to look in app/assets/javascripts and lib/assets/javascripts, and will tell jasmine-headless-webkit to pull every possible file in both directories. Jasmine's normal file requiring wouldn't be used in this case, just Sprockets.
Then, set up your require statements like you would normally in your JS files. So in 'application.js.coffee':
#= require jquery-1.6.4
#= require avia
#= require underscore
#= require backbone
#= require jquery.jqGrid.min
#= require_tree .
alert "Look, Internet codes!"
And in avia_view.js.coffee:
#= require views/avia_view_template.jst.hamljs
class window.AviaView extends Backbone.View
template: JST['views/avia_view_template']
... code ...
Of course, those .hamljs templates won't get loaded unless a Sprockets-capable Haml processor has been loaded. So you would want to have a Gemfile that had at least this in it:
gem 'jasmine-headless-webkit'
gem 'haml-sprockets'
# also bring in backbone and jquery
gem 'jquery-rails'
gem 'backbone-rails'
Then, if your application itself knows what to do when those vendored JS gems are loaded, you could get rid of you own copies of jQuery and Backbone, and you'd also have .hamljs templates available. At that point, you should run using Bundler:
bundle exec jasmine-headless-webkit
Last thing, the best way to make sure everything's actually getting loaded is to use the list option:
bundle exec jasmine-headless-webkit -l
That will run everything through JHW's and Sprockets' file loaders and print out the order of files to be included. This will help diagnose require problems, since you always have to deal with both Jasmine-style and Sprockets-style loading in a single scenario. Setting up your src files to be loaded entirely via Sprockets simplifies the process a lot, so I would recommend a setup a lot like this one.

Related

How are Sprockets directives read in manifest file when using Rails?

New to Rails so bear with me...I was looking at a manifest file (application.js) today while researching the asset pipeline and was curious how the directives such as //= require jquery are being read. Is this something Sprockets is doing in the background? How? Why must the directive be commented out first, and the equal sign added? If I uncomment the directives and load the application.js file in my broswer, I no longer see the jquery library contents. Just curious how this is working in the background.
Also, when I add my own custom css stylesheet, do I add a require directive in the application.css manifest file, or do I add the stylesheet link such as <link rel="stylesheet" type="text/css" href="mystyle.css">? Or do I do both? I'm assuming I shouldn't add css directly inside of the manifest file...
Thanks!
Dont know how much you know, so will try to explain in details.
Rails stores our assets (like images, css, js files) in separate places, so its all in order and better for us - devs, to use. So thats called Assed Pipeline. When Rails loads those assets, say, css files, it creates one big file from all our app files, to avoid multiple calls. And Manifest is like a map or rules for Rails which files to include in that big css file and this *= is whats telling Rails what exactly to include (I consider it as a Rails syntax). So when you have something like this:
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
require_tree . tells Rails to grab all files from the javascripts folder, while //= require jqueryand others directs Rails to special cases - assets, usually used by your gems (those files you never keep in your javascripts/stylesheets folders, so //= require_tree . cant see them).
When you add your on css file, you just add it in the stylesheets folder and require_tree informs Rails to include it in the big picture. But Rails has a nice feature - scaffolding. You scaffold your object with command rails g scaffold User and Rails creates everything for you - views, controller, model, tests (and who knows what else :) ). So in this case you don't even need to create your css file, just insert css rules into it and Rails will find it due require_tree .
A bit different story with sass files:
If you want to use multiple Sass files, you should generally use the
Sass #import rule instead of these Sprockets directives. When using
Sprockets directives, Sass files exist within their own scope, making
variables or mixins only available within the document they were
defined in.
So if you will be using Bootstrap (probably will), this is a important to know as well.
Hope this helps
How? Why must the directive be commented out first
Because this is sprockets directive. It is executed well before any js/coffee in that file gets the chance to run. And css is not "runnable" code at all. How do you make this kind of code not produce any errors? You comment it.
... and the equal sign added?
To tell these special directives apart from other, "regular" comments, which may be in that file.
I'm assuming I shouldn't add css directly inside of the manifest file...
Why not, go ahead. Although you may want to put any custom code in separate files for reasons of code organization. But technically, there's no problem here.
Also, when I add my own custom css stylesheet, do I add a require directive in the application.css manifest file
No need, require_tree . will find and include your file.
or do I add the stylesheet link such as <link rel="stylesheet"type="text/css" href="mystyle.css">?
Nope, don't do that.

RequireJS include dependency only in build

I'm using html2js plugin to compile my Angular templates ( this is not really relevant but wanted to explain ).
It builds a templates.js during the build process that requires angular to be in scope like:
angular.module("views/date.html", ...... ");
so essentially I need this file to be in the main.js dependency chain. Now I was able to get it to be included in the build doing:
deps: ['templates']
in my build.config for require but its never 'required' by any modules so it never executes.
Bottom line: In require, how can I require a file at the top of the dependency chain only at build time?
Ended up setting a variable in the html page if in dev mode like:
<script type="text/javascript">window.dev = true;</script>
then made a require statement like:
if(!window.dev){
require(['templates', ... ]);
else
// don't include templates

Ruby on Rails - how require is executed in application.js

I am reading a book for "Ruby on Rails". In the "application.js", we are including other JavaScript libraries in the following way and more specific - jQuery UI:
//= require jquery
//= require jquery_ujs
//= require jquery-ui
As this is ordinary JavaScript file (not ruby extensions here like "html.erb" for exmaple) how the application knows to execute the require command? What kind of JavaScript syntax is this:
//=
and as this is ordinary JavaScript file, why we are not using "script" tags to include JavaScript files?
Also, I have read here that "require" method will check for this library in define by $LOAD_PATH variable folders. How can I see where the "jquery-ui" is stored? I am asking because in other applications in order to use jQuery UI I should add not only JavaScript file, but css file and images used by the library - in this case, we are doing this only with single line?
What kind of JavaScript syntax is this.
Anything starting with a // is a Javascript comment.
How is it able to process it ?
Sprockets on the server side scans the JS file for directives. //= is a special Sprocket directive. When it encounters that directive it asks the Directive Processor to process the command, require in this example. In the absence of Sprockets the //= require .. line would be a simple JS comment.
Ruby require vs Sprockets require
These are two completely different things. The one you link to is Ruby's require.
Why not use script tags to load JS files.
Usually, you want to concatenate all your app JS files and then minify them into 1 master JS file and then include that. I recommend reading the YSlow best practices on this.
I also recommend watching the Railscasts on Asset Pipline - http://railscasts.com/episodes/279-understanding-the-asset-pipeline
Cheers!

namespacing 3rd party js libs using rails 3 asset pipeline

I'm using the Rails3 asset pipeline for js. I'd like to wrap some third-party libs in a namspace, but I can't get it to work. For example, this
var myns= function() {
//= require swfobject
};
produces literally:
var myns= function() {
//= require swfobject
};
That is, the require wasn't invoked. Is the asset pipeline syntax so fragile? Where is this limitation documented? Is there a workaround or better way?
First time I see this use case of assets pipeline.
Anyway you should check the sprockets documentation https://github.com/sstephenson/sprockets (The Directive Processor)
Sprockets runs the directive processor on each CSS and JavaScript
source file. The directive processor scans for comment lines beginning
with = in comment blocks at the top of the file

What can cause Rails 3.1 "= require jquery" to stop working?

I'm porting a Rails 3.0.9 app to Rails 3.1.rc5. My application.js is exactly the same as one generated by Rails 3.1 itself:
// This is a manifest file ...
//
//= require jquery
//= require jquery_ujs
//= require_tree .
But when I run my app and look at the application.js in Firebug or Chrome Developer Tools, all I see is:
// This is a manifest file ...
//
The directives are gone, so it would seem that the file has been processed by Sprockets, but the directives have not been replaced by the contents of jquery et al. There are no errors appearing on the server console or in the logs.
Curiously, when I run a blog app (you know, the canonical tutorial app) it works fine (that is, when I examine application.js in Firebug, it contains the text of jQuery.) This would seem to indicate that something in my app is somehow interfering with Sprockets. Has anyone out there heard of such an issue (and hopefully a workaround)?
Here's my setup:
$ gem list jquery
*** LOCAL GEMS ***
jquery-rails (1.0.12)
$ ruby -v
ruby 1.9.2p290 (2011-07-09) [i386-mingw32]
$ rails -v
Rails 3.1.0.rc5
I'm at a loss as to what might be wrong. I've triple checked my Gemfile; I've run and re-run bundle install and bundle update; I've tried rc3, rc4 and now rc5; I'm running Ruby 1.9.2p290. Any ideas?
One workaround: include JavaScript files with the old-skool tag. For example, in my (Haml) layout:
= javascript_include_tag '/assets/jquery.js'
= javascript_include_tag '/assets/jquery_ujs.js'
= javascript_tag 'jQuery.noConflict();'
The /assets/ prefix tells Rails 3.1.x to look on the asset path, which includes gems, so you'll get the same files as with Sprockets directives. But you won't get concatenation or any other Sprockets preprocessing.
Still looking for better solutions.

Categories

Resources