Jasmine - what connects a source to spec file? - javascript

Just getting started with Jasmine. I understand you put (like Rspec) the spec file in the javascripts folder with a naming convention of <file_name_to_be_tested>_spec.js
That's great!
So I have spec/javascripts/orders_new_spec.js
I've discovered that I can use the above to test EITHER of the files below:
app/assets/javascripts/orders/new.js
app/assets/javascripts/orders_new.js
But for someone like me who does have a somewhat complex file directory... I need a way to differentiate the two... Right now of course the jasmine.yml looks like this:
src_files:
- assets/orders/new.js
- assets/orders_new.js
But since there's ONE yml file for all specs, it doesn't serve as a differentiator.
Is there some way to, in the spec file itself do it? E.g.,
# /spec/javascripts/orders/new_spec.js
require 'assets/orders/new.js` # and ignore jasmine.yml
describe...
# /spec/javascripts/orders_new_spec.js
require 'assets/orders_new.js` # and ignore jasmine.yml
describe...

The formal answer is no. Of course there are ways of hacking around it. From the Jasmine Github mods:
Jasmine (especially in the browser) doesn't have any relationships between which spec file tests which implementation file. If you have a subset of files that can't be loaded in the same page as some other subset of files, you probably want to have multiple jasmine.yml files and use the JASMINE_CONFIG_PATH environment variable to pick the right one when running your tests. This would mean you need to run two (or more) jasmine:ci tasks to run all of your specs.
The other option would be to refactor/rework your implementations so that all of the files can be loaded into the browser at the same time and just instantiate the underlying objects in your specs.

Related

How to configure dynamic loading?

I'm using webpack 4.26.1 (latest).
The code import('./images/header.csv') produce the following error:
Uncaught (in promise) Error: Cannot find module './images/header.csv'
at webpackMissingModule (home.js:9)
My project structure:
'project-dir/src/components/home.js' (im here)
'project-dir/src/components/images/header.csv'
I tried to read https://webpack.js.org/api/module-methods/ but failed to understand what to do except adding random webpack comments which I don't understand.
Also, from the docs, I may be found the source of the problem but I'm not exactly sure I understand it and how to solve it.
Fully dynamic statements, such as import(foo), will fail because webpack requires at least some file location information. This is because foo could potentially be any path to any file in your system or project. The import() must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.
Every module that could potentially be requested on an import() call is included. For example, import(./locale/${language}.json) will cause every .json file in the ./locale directory to be bundled into the new chunk. At run time, when the variable language has been computed, any file like english.json or german.json will be available for consumption. Using the webpackInclude and webpackExclude options allows us to add regex patterns that reduce the files that webpack will bundle for this import.
More than providing me a solution, I will appreciate any answer that covers what is the actual problem with my code.
Thank you.

What's the best way to concatenate vendor js files?

In my Angular JS app, I'm using a lot of third party packages, mainly maintained via Bower.
When I use Grunt to concatenate all of them into one mega file, I'm getting errors when I load my page, for example that
Uncaught ReferenceError: angular is not defined and
GET http://localhost:8080/theproj/v4/dist/app/bootstrap.css.map 404 (Not Found)
What is the best way to properly concatenate all these files to ensure that everything loads in the right order and doesn't cause problems?
First issue: A lot of times third party libraries must be loaded in a particular order. That looks like like it's the source of your first issue. Something is trying to use angular and it's getting loaded before the angular code. You should refactor your grunt task to use a pre-defined order for third party libraries.
Second issue: You probably are missing the .map file. This is a file used by Chrome dev tools to show you the original source for the css (sass or less). Either provide the map file, or delete the reference to it from bootstrap.css. Or just ignore the error, it's only an error when you have chrome dev tools open, and doesn't actually affect your application.
For the issue of the correct order for your javascript files, i had that problem in a larger project where noone really had a clue which was the correct order.
Luckily we found that the Google Closure Compiler does exactly this: https://github.com/google/closure-compiler
You give it all your js files and it analyzes them all and concatenates them in order
$ java -jar compiler.jar --js_output_file=out.js in1.js in2.js in3.js ...
There is even a grunt plugin for the connection: https://github.com/gmarty/grunt-closure-compiler
'closure-compiler': {
frontend: {
closurePath: '/src/to/closure-compiler',
js: 'static/src/frontend.js',
jsOutputFile: 'static/js/frontend.min.js',
maxBuffer: 500,
options: {
compilation_level: 'ADVANCED_OPTIMIZATIONS',
language_in: 'ECMASCRIPT5_STRICT'
}
}
},
Another way would be to change your javascripts into AMD or CommonJS modules, this way you don't have to worry about the correct order. RequireJS (http://requirejs.org/docs/start.html) is a possibility for AMD for example or Webpack (http://webpack.github.io/) ...or many many others.

Yii2: Registering Asset Bundle vs registering external Js file

Hi I wanted to know the advantage of registering Asset Bundle following the process described in the docs like
Process one
in AppAsset.php
public $js = [
'js/myjsfile.js'
];
then in the view file
adding Namespace like
namespace app\assets;
and then adding the use statement like
use app\assets\AppAsset;
AppAsset::register($this);
Instead of doing all this if I use
Process Two
$this->registerJs('js/myjsfile.js', $this::POS_READY);
it works fine.
So why should I use Process One.
Any advantage and reason for this will be greatly appreciated.
If I follow the process one Do I need to add all the js files in
AppAsset.php individually.
Thanks.
Asset Bundles have some advantages over normal registering. Apart from what #deacs said in his/her answer here are others:
Assets Bundles can publish the file to assets if its not in web accessible directory
Assets Bundle can deal with less files (in case of CSS) as well as compressing the assets.
Makes Code Elegant especially in solving dependencies and hence reusability
All the features that makes bundles shine are found in docs
One of the main reasons for using an Asset Bundle is that your assets' paths will always be correct. Consider:
$this->registerJsFile('js/myjsfile.js', ['position'=>$this::POS_READY]);
will generate something like:
<script src="js/myjsfile.js"></script>
Which works great for non urlManager enabled urls, e.g. http://localhost/yiiproject/index.php?r=user/update&id=8 because your browser looks for the js file at: /yiiproject/js/myjsfile.js
But if you enable urlManager, your url will look like http://localhost/yiiproject/user/update/8, which means your browser will look for your js file at: /yiiproject/user/update/8/js/myjsfile.js.
You could overcome this problem by using:
$this->registerJsFile(Yii::$app->request->baseUrl.'/js/myjsfile.js', ['position'=>$this::POS_READY]);
But the Asset Bundle basicly does that for you.
Using Asset Bundles, you can also get the latest version from 'vendor' folder, so if you need to update some lib you don't need to manually do this since composer already do this.

How to include minified library version in RequireJS optimization

My situation is as follows:
My project based on RequireJS.
I am using RequireJS Optimizer for to create a single JS file.
Some of the module use a certain third party library as a dependency.
The third party is NOT included in the optimized file (libName: empty
in the build config).
RequireJS is configured through var require = {} object which appears
on EACH PAGE, right above the RequireJS. The object defines a path to
the unminifed version of the library, among other things.
What i'd like to achieve:
Use the same config file in both development and production (the require={} object is included with tag on each page). During development I'd like modules to use the UNMINIFIED version of the third party.However, after optimization occurs, i would like all the modules to use the minified version of that third party.
I did think of a solution in theory, but it seems a bit messy and Im hopeful cleaner solution exists:
To have the runtime config point to unminified version
var require = {
paths:{
'thirdParty':'lib/thirdParty'
}
}
Create a module which execute (lets call it "PathRewrite" Module):
requirejs.config({
paths:{
'thirdParty':'lib/thirdParty.min'
}
})
In runtime configuration, define path to "PathRewrite" as empty
var require = {
paths:{
'thirdParty':'lib/thirdParty',
'PathRewrite':'empty'
}
}
In the build configuration file define a real Path to "PathRewrite" in order for it to be included in the "main" file (concatenated file after build).
Include "PathRewrite" as a dependency of a module which is executed first.
What I hope that will happen is that during dev, when optimized file is not used, PathRewrite is will not be used, hence the path to unminified third party in the runtime config will be used.
When the project is optimized, PathRewrite will be included and executed. According to RequireJS documentation, it is possible to run RequireJS configuration twice and the configuration will be appended/overwritten. PathRewrite execution will overwrite the path to "thirdParty" to minified, which will thus be used by all the modules.
Hopefully i've provided enough information. I'd be glad hear of other ways to get this done. Thanks in advance.
This topic appears to have been explored a bit in this answer:
Loading min.js files Generated by TypeScript with Require
Don't let the title discourage you. Typescript is not the core issue of the question being answered there. Unfortunately, the discussion reveals that the RequireJS optimizer may be the only way to get decent minification to work, as it seems incapable of selecting alternate paths properly.
Why don't you want to use inbuilt RequireJs optimizer? You may just include this option
optimize : "uglify2"
and all your and third-party code will be minified after concatenation. In this case you don't need to use minified versions of third-party libraries.

How to structure a JavaScript project?

I'm currently working on a big JavaScript project for which we want to define our own API. I'm using RequireJS as my dependency loader and it suits me just fine, allowing me to define modules in their respective file. I do not make use of my own namespace, a module returns an instance, which can be used in other modules, i.e.:
define(
['imported_module'],
function(module){
module.doSomething();
}
)
However as the number of files grows, I'd like to decide how to structure these files in folders. Currently I use the following scheme to name my files:
[projectname].[packagename].[ModuleName]
An example could be stackoverflow.util.HashMap.js. I would like to introduce a project folder, a folder per package and rename the files to the module name, like:
stackoverflow/util/HashMap.js
This structures my code quite neatly into folders, however the filename reflects only the module now. I'd like to define some kind of routing to be able to define how RequireJS should look for files. Example:
The file
stackoverflow/util/stackoverflow.util.HashMap.js
Should be importable by the statement
define(['stackoverflow.util.HashMap'],function(HashMap){});
Has anyone experience with structuring large JavaScript projects and if so, could you share your approach?
You shouldn't specify the routing info on your js file names, those are the namespace and folder paths' jobs. So stackoverflow/util/HashMap.js is just fine. And you can use define("stackoverflow/util/HashMap", ....) to tell the dependency.
If you need to put your modules in a different folders, you can config paths for your loader, see this manual from RequireJS API.
There's no best way for structure your js files. But put the root namespace in a src folder is always a good practice. You can see the dojo source code and YUI source code and use similar ways for your project. They both are large scale Javascript projects.
actually it's better to get js lib routing to load all js using standard interface: "js.yoursite.com/lib-0.2.js" there should be a router (php or other, and able to cache queries). So there you could determine and control whole pathes that you use. Because common jquery plugin should stay at one dir, with jquery, and your own custom plugins not.
And there you control each project by it's own rules:
jquery/
plugins/
jquery.prettyPhoto.js
jquery.min.js
mySuperJS/
stable.0/ -- there your production version for 1.0 branch
module.js
0.1/
module.js
0.2/
module.js
0.3/
module.js
myOtherlib/
stable.0/ -- production version for all 0.* versions
stable.1/ -- production version for all 1.0 versions
0.1/
0.2/
0.3/
0.4/
0.4.1/
0.4.1.18/
We're using such structure around a year and it's the best for us. But sometimes we use more complex solution and separate all modules for libs, plugins, tools, components and apps.

Categories