In my unit test (written with protractor) I need to write functions that should be used in several tests in several files (and only in unit tests).
How can I create those functions?
The best solution is to declare the functions in a single file to include in the test files that I need, but I don't know how to do it without creating global variables or global functions.
If you would follow the Page Object pattern, you would not be in a situation like this. All of the functions you need would be tied to page objects, you would have a nice separation of concerns and any changes in the element selection logic would be like a breeze. You can also think about page objects as global libraries available in your tests.
See also how can you apply the pattern using protractor:
Using Page Objects to Organize Tests
Related
I am about to write a common Angular module which can be used as a plug and play module in my application.
What I want
I want to put the module definition and all its factory, directive, constants in a single js file, example:
angular.module('commonModule', [])
.factory(...)
.directive(...)
.constant(...)
Why because
Whenever a developer wants to use my module he/she just need to call a single js file and just need to inject my module in their module.
What is my problem
I have read the John papa's Angular 1 good practice style guide, he told that it is good to define a single component in a file, but here I am doing the opposite so what should I do?
Separate. Just so and not otherwise.
Keeping components separately is one of the best practices in programming world. No matter if you have few lines of code at the moment, later code will increase. Doing so from the beginning you cultivate a literate programming discipline. Bad practice to come up with a bunch of exceptions in the rules, like "if I have few lines of code I can write all components of my app in one single file". It makes rules and possibility to follow them more complicated.
Whenever a developer wants to use my module he/she just need to call a
single js file and just need to inject my module in their module.
Correct. For consumer it is very convenient to include just one single file in his/her project. But it is bad for code maintenance. So just use any JS bundler to concatenate all dependencies in one result file so consumers can just inject it in their module.
Singletons are a bad idea for the most part. I believe everyone is on board with this concept. I am wondering why does Angular rely so heavily on factories for its dependency injection considering factories are singleons ? Why are singletons not a bad idea in Angular ?
Singleton is not considered a 'good practice' when accessed directly, through global class name (in java) or as a global variable. Your code is coupled with it and difficult to reuse and unit test. Changes in one class/module can cause a side effect in another one without you being able to execute those modules independently.
In Angular it is injected as a dependency - a function parameter. So it is a different thing. You can easily pass different implementation of you singleton to one function and different to another (if you wanted). Your code explicitly declares it as dependency and allows the client (caller) to pass whatever he wants instead of hiding it internally.
I am using angular seed project
https://github.com/angular/angular-seed
where should I put the services and directives ?
This is really totally up to you but there are some good recommendations on project structure here: https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
Typically my structure looks something like
app\scripts\user.js
app\scripts\todo.js
Where User.js would have a service and possibly multiple controllers in it... if the file gets too large then I break it up into parts.
The problem with grouping all services together and all controllers is that the services and controllers typically have a relationship (functionally). When you want to re-use the service/controller you are typically going to use them together, when editing one you usually need a reference to the other. This makes it easiest to find things and not have 1000 js files to include and manage in the dependencies and script inclusions.
Also when it comes time and you want to make a bower component out of one of the sections it's easier to see which parts need to be pulled out.
You can make a folder for each under app, so your project tree will look like this:
app/directives
app/services
I have an application made with angularJS, whole application is composed of IIFEs(Immediately Invoked Function Expression). Every module, directive, controller is itself an IIFE and they are around 100s.
I want to know what is the performance pitfall when an app has so many IIFEs.
It is OK to use IIFEs with AngularJS?
How good is using libs like browserify and requirejs with AngularJS for managing the dependencies?
Can you please throw some light on this?
The question you need to ask first is whether you've got some internal parts within the IIFE that you don't want to expose to the global scope.
The whole point of creating a closure in this manner is to mimic encapsulation and avoid polluting the global scope.
The performance pitfall is not so easy to measure; I think the performance issue is negligible when you create the IIFE (don't forget you're just creating a function). One performance issue that I might think of is that when you reference a function variable form an inner function, you need to travel through the scope chain and get it from the closure object.
I would recommend you to look at patterns like module pattern, revealing module pattern etc. I personally use the revealing module pattern.
Browserify and requireJS are two libraries that implement two different specs; the commonJS and AMD respectively. These two specifications try to accommodate a functionality that is not supported by ES3 or ES5; That is a way of defining module and then loading them in specified locations.
If you want to define modules and load them synchronously in a similar manner to hose nodeJS works, you can use Browserify. In addition, Browserify allows you to use the same modules both for client-side and server-side (as long as you're using nodeJS).
On the other hand if you want to asynchronously load your modules you can go with AMD and requireJS, but you won't be able to reuse them on the back-end.
Finally, bare in mind that everything you've mentioned is not directly connected to angularJS; those are some good JavaScript practises to overcome some issues of the language itself. It can be well used whether you're working with angular or not.
I would recommend that you use either browserify or requireJS; it will benefit you in the long run. Just imagine having 100 JS files; you would need to out the manually into your html in the correct order based on the dependency graph. You can easily come across issues like race conditions where one file should have been inserted before another one.
As for the performance overhead of IIFEs, you shouldn't have any serious issues.
As another answer said, IIFEs are a good general practice, independent of AngularJS.
If you're concerned about the performance of IIFEs, go ahead and check out these performance tests on JSPerf (or write your own):
http://jsperf.com/iife-antecedents-in-js
http://jsperf.com/immediate-anonymous-function-invocation
While some ways of IIFE creation are clearly much slower than others, I wouldn't worry about the performance of IIFEs unless you're in a large loop.
I've written a helper to help with generating URLs in my CakePHP 2.3 app. Basically it's a wrapper around Cake's built-in functionality, that helps handle routing prefixes, avoids key/value array pairs for common things, etc, to make the code a bit tidier.
The problem is, I need basically all the same functionality for easily generating these URLs from my helper, available in my controllers - for things like loginRedirect, redirecting after edits, etc.
Is there a good solution for sharing logic between Controllers and Views without duplicating code? I understand that in general Views and Controllers shouldn't share code - but there are exceptions.
You can create a 'Utility' and create 'Helper' and 'Component' wrappers for that, that can be used inside your Controller and Views, something like the TextHelper / String Utility combination.