Karma + Rails: File structure? - ruby-on-rails

When using the karma javascript test library (née Testacular) together with Rails, where should test files and mocked data go be placed?
It seems weird to have them in /assets/ because we don’t actually want to serve them to users. (But I guess if they are simply never precompiled, then that’s not an actual problem, right?)

Via this post: https://groups.google.com/forum/#!topic/angular/Mg8YjKWbEJ8
I'm experimenting with something that looks like this:
// list of files / patterns to load in the browser
files: [
'http://localhost:3000/assets/application.js',
'spec/javascripts/*_spec.coffee',
{
pattern: 'app/assets/javascripts/*.{js,coffee}',
watched: true,
included: false,
served: false
}
],
It watches app js files, but doesn't include them or serve them, instead including the application.js served by rails and sprockets.
I've also been fiddling with https://github.com/lucaong/sprockets-chain , but haven't found a way to use requirejs to include js files from within gems (such as jquery-rails or angularjs-rails).

We ended up putting tests and mocked data under the Rails app’s spec folder and configuring Karma to import them as well as our tested code from app/assets.
Works for us. Other thoughts are welcome.
Our config/karma.conf.js file:
basePath = '../';
files = [
JASMINE,
JASMINE_ADAPTER,
//libs
'vendor/assets/javascripts/angular/angular.js',
'vendor/assets/javascripts/angular/angular-*.js',
'vendor/assets/javascripts/jquery-1.9.1.min.js',
'vendor/assets/javascripts/underscore-min.js',
'vendor/assets/javascripts/angular-strap/angular-strap.min.js',
'vendor/assets/javascripts/angular-ui/angular-ui.js',
'vendor/assets/javascripts/angular-bootstrap/ui-bootstrap-0.2.0.min.js',
//our app!
'app/assets/javascripts/<our-mini-app>/**',
// and our tests
'spec/javascripts/<our-mini-app>/lib/angular/angular-mocks.js',
'spec/javascripts/<our-mini-app>/unit/*.coffee',
// mocked data
'spec/javascripts/<our-mini-app>/mocked-data/<data-file>.js.coffee',
];
autoWatch = true;
browsers = 'PhantomJS'.split(' ')
preprocessors = {
'**/*.coffee': 'coffee'
}

I found this project helpful as a starting point. https://github.com/monterail/rails-angular-karma-example. It is explained by the authors on their blog.
It's an example rails app with angular.js and karma test runner.

Related

Webpack: split some entries to chunks, but others - don't

Is it possible to have one webpack dev server that's configured with multiple entry points (there are multiple pages on the site), each with a different configuration?
Specifically, I want one entry (the page's JS code) to be split into chunks, but another entry (JS localization bundle with translated messages) not to be chunked.
One possible complication, which you may ignore if you wish, is that I'm using Ruby-on-Rails webpacker, which automagically creates some of the webpack configuration for me.
You might be able to use a function for optimization.splitChunks.chunks to exclude your localization bundle by name as shown in the example in the Webpack docs: https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkschunks
In Webpacker land, it might look like the following:
environment.splitChunks((config) => Object.assign({}, config, {
optimization: {
splitChunks: {
chunks(chunk) {
// exclude `my-excluded-chunk`
return chunk.name !== 'my-excluded-chunk';
}
}
}
}))

How do I configure my grails app to skip preprocessing images?

I've been asked to remove any images duplicated in the war file our grails app is packaged in. The documentation suggests this is possible via the grails.assets.excludes property in Config.groovy, but it doesn't clearly state how this property is supposed to work.
Here's what the documentation says:
Optionally, assets can be excluded from processing if included by your require tree. This can dramatically reduce compile time for your assets. To do so simply leverage the excludes configuration option:
grails.assets.excludes = ["tiny_mce/src/*.js"]
The example is totally unclear to me. I've tried several permutations of this expression with no success; image assets continue to be preprocessed, causing duplicates of all of them in the resulting war file. Here are a few settings I've tried:
grails.assets.excludes = ["tiny_mce/src/*.jpg", "tiny_mce/src/*.jpg"]
grails.assets.excludes = ["<app_name>/src/*.jpg", "<app_name>/src/*.jpg"]
grails.assets.excludes = ["/images/*.jpg", "/images/*.png"]
grails.assets.excludes = ["**/*.jpg", "/images/**"]
What am I missing? How do I tell the asset pipeline to skip precompiling images?
This works for me:
grails.assets.excludes = ["**/*.jpg","**/*.png"]
I can't get any rule based on images/ to work...

Exposing static files in Ruby on Rails 3.1+?

I want to use SoundManager2 to play sounds in my Ruby on Rails application. One of the things it wants is a directory with swfs. Where do I put it and then how do I configure my soundmanager? I want to put them in a directory /soundmanager/ and use JS such as the following:
<script>
if (soundManager) {
soundManager.setup({
url: '/soundmanager/',
onready: function() {
var myGameMusic = soundManager.createSound({
id: 'music1',
url: 'music1.wav'
});
myGameMusic.play();
},
ontimeout: function() {
console.log("Error in soundManager.setUp")
// Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
}
});
}
</script>
Where do I put the swfs (/soundmanager/) and how do I configure it to be public?
A related question is: suppose I have some PDFs that I want to make downlaodable. Where do I put those so that they're downloadable?
I'm confused because there is a /public directory but apparently it doesn't work in rails 3.1 anymore.
You put them in app/assets/
The key is that they are served from there in development mode.
In production mode, the assets are minified and placed in public/
This is called 'asset compilation' and was introduced in Rails 3.1 and has caused a lot of confusion as you have seen.
The web server should be serving static resources alongside Rails (not through Rails).
I had to do this to get a phpMyAdmin installation working with a Rails app on Apache/Passenger.
# Apache vhosts.conf
<Location ~ "/static_content">
PassengerEnabled off
</Location>
This serves content in /static_content directly from Apache, bypassing Rails completely. Ideally, this is the optimal solution to static content in any case.

Conditional javascript require in the asset pipeline

I'm struggling with the asset pipeline. I'm loading dojo from Google CDN putting this in my template:
= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js', :'data-dojo-config' => %Q(dojoBlankHtmlUrl:'/blank.html', baseUrl: 'assets/', modulePaths: {custom: 'javascripts/modules'})
I just want a fallback to a local version if running locally or if the CDN is down. I thought of doing this:
script typeof(dojo) === "undefined" && document.write(unescape('%3Cscript src="js/libs/dojo-1.6.1.min.js"%3E%3C/script%3E'));
But I don't like it as it works out of the asset pipeline. I want to keep dojo in vendors/assets/javascripts/dojo. How can I get the fallback to be served by the asset pipeline.
Is there a way do declare conditional require in the asset pipeline. What I want is to run some javascript tests, and depending on the result serve a file.
Thanks
I suggest you use yepnope, a lightweight library for loading libraries like this in parallel (for speed) and it gives you the option to run some other code to test if the library is loaded. For example:
yepnope([{
load: 'http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js',
complete: function () {
if (!window.jQuery) {
yepnope('asset_path('you_local_copy_of_dojo') ');
}
}
}])
(Note: You will need erb tags around the asset_path helper)
The local dojo file would be in the assets/javascript folder, but not included in the application manifest. You need to add the dojo file to the precompile array:
config.assets.precompile += 'your_local_file.js'
And this will make it available to the asset_path helper.
Thanks Richard!
I don't want to have yepnope to load one library. It would be overkill imo. Here is the solution I came up with, based on your help (written in slim):
1/ In vendors/assets/javascripts/, I have my dojo.js.
2/ In config/application.rb:
# Precompile these assets files
config.assets.precompile += ['dojo.js']
3/ In the template:
= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/dojo/#{Settings.dojoVersion}/dojo/dojo.xd.js", :'data-dojo-config' => %Q(dojoBlankHtmlUrl:'/blank.html', baseUrl: 'assets/', modulePaths: {custom: 'javascripts/modules'})
script = "typeof(dojo) === \"undefined\" && document.write(unescape('%3Cscript src=\"#{asset_path('dojo')}\"%3E%3C/script%3E'));".html_safe
I also posted on the Rails Google Group to request the addition of two options to the javascript_include_tag, :test and :local that would take care of all the work. We'll see.

Dojo custom build with NLS / localisation

I have a problem implementing a cross domain custom build in Dojo.
The situation is as follows: i have a pretty large application, with a good number of localisation bundles, so basicly the directory structures is like
core\ (my module)
nls\
fr\
en\
....
When building my module the result is a big core.js/core.xd.js file, which, bien sur, does not contain the localisations. In the localisation nls directories (en/fr/etc) i find after the build each bundle builded/minified, and a bigger file for each language, core_fr.js/core_en.fs, which contains only Dojo/Dijit related strings.
so my build script is
layers: [
{
resourceName: "core",
name: "../core/trusted.js",
dependencies: [
"dojo.i18n",
//data
"dojox.data.JsonRestStore",
"dojox.data.XmlStore",
"dojox.rpc.Service",
"dojox.form.FileInput",
...
"core.controller.Fusebox"
],
prefixes: [
["dijit","../dijit"],
["dojox","../dojox"],
["core", "../core"]
]
In the core.controller.Fusebox class i try to load 1 nls
dojo["requireLocalization"]("core", "FuseboxContent");
here it will die, however with
availableFlatLocales is undefined
[Break on this error] var locales = availableFlatLocales.split(",");\r\n
My config in the html file is :
// version build
var djConfig = {
baseUrl: 'https://..../',
modulePaths: { 'core': 'core'},
useXDomain: true,
xdWaitSeconds: 10,
parseOnLoad: true,
afterOnLoad: true,
// debugAtAllCosts: true,
isDebug: true,
locale: "fr"
};
and then
<script type="text/javascript" src="http://xd.woopic.com/dojoroot/1.3.2-xd/dojo/dojo.xd.js.uncompressed.js"></script>
<script type="text/javascript" src="https://..../core/trusted.js.uncompressed.js"></script>
I used the uncompressed for debug, of course.
The problem is that, on runtime, Dojo tries to load my bundles and can not find them, and i would like to embed them in my layer file, so no extra loads will be required.
Can this be achieved? And while we're at it, are there any working sites/examples with cross domain localisations?
UPDATE: i continued my analysis and the problem seems to lay in the fact that i am dynamicaly loading nls, so the build parser can not find the requireLocalization() calls. Therefore the project nls file contains only dojo/dijit related content. However, i added a few bundle loads in a dummy file, and the content of core/nls is still ignored by the builder.
Thanks for any info, i am pretty much at the end of my searches, there isn't much on the net on this subject.
I had a similar issue a few days ago. First of all, you can get around the error by setting the available locales as the 4th parameter of the requireLocalization call.
e.g.
dojo.requireLocalization("core", "FuseboxContent", null, "en,fr");
though you should not have to do that.
Did you try including the localization as follows?
dojo.requireLocalization("core", "FuseboxContent"); // and not dojo["require..."]

Resources