Loading ngMock only in testing context when using Protractor - angularjs

I'm switching all of our protractor E2E tests of an angular app to ngMock, so that we can mock our resources/http calls. However, I can't find a recommended method for loading ngMock in that scenario.
I don't want to include the script itself in my live app of course, but I'm not seeing a clear method through protractor for injecting an extra script element, or dynamically loading it.

You can do is to use grunt-targethtml or gupl-targethtml so in your index.html you can add conditions of when to add an script or not:
<!--(if target mock || e2e)><!-->
<script src="dev-mocks/mock-utils.js"></script>
<script src="dev-mocks/modules/authentication-service-mock.js"></script>
<!--<!(endif)-->
First configure your grunt task to execute the targethtml task with the target e2e/mock
grunt.registerTask(
'e2e',
'Automated tests',
function(target) {
var tasks = [
'clean:server',
'targethtml:e2e',
'concurrent:server',
'autoprefixer',
'connect:e2e'
];
return grunt.task.run(tasks);
});
Here is a working template with all the tasks, packages and logic necessary to implement Protractor + CucumberJS + sugar-step (for easy sync-async steps executions), and also inject mock modules dinamically using the #Around method of CucumberJS

Related

How to fix the below test case when i am migrating from angularjs 1.6.9 to 1.7.8

i am trying to migrate my angularjs application from v1.6.9 to v1.7.8. my test case are failing with
angular-mock.js($rootScope)
ERROR: No response Defined! in angularjs/angular-mocks.js(1607)
ERROR:$rootScope:INPROG
since i am new to jasmine karma testing i have tried with $rootscope.flush(). but i am not able to resolve it .
this is my first unit testing with Angularjs and jasmine karma, not able to find the exact reason and i have gone through the release notes of the other releases as well.
with $rootScope i found that they have modified its scope to the function not generic.
Below is my spec.js:
I am getting error with $rootscope,flush(). could some please help me out to resolve this issue as it is required.
$httpBackend.when('GET','/application/api/prefernce-definition')
.respond(successResponsePrefernces);
$httpBackend.when('POST','/application/api/setprefernce-definition')
.respond(201);
$httpBackend.when('POST','/application/api/v1/set-prefernces');
$httpBackend.when('POST','/application/api/v2/balances')
.respond(accountApiResponse);
//assertion for expecting proper get request for preferences-definition
$httpBackend.expectGET(,'/application/api/v1/prefernce-prefernces');
//fetch and set prefernces
$scope.onclickSetting();
$rootScope.flush();
$timeout.flush();
//now save the settings
$scope.saveViewSettings();
// getting error in this line after the flush
$rootScope.flush();
$timeout.flush();
var viewMode = $scope.model.viewSettings.viewMode,
viewModeExpected = successResponsePreferences.preferenceDefinitionList[0];
expect(viewMode.default).toBe(viewModeExpected.defaultPreferenceValue);
expect(viewMode.selected).toBe(viewModeExpected.currentUserPreferenceValue);
expect($scope.$broadcast).toHaveBeenCalledWith("ShowFilter");
//should update the prefernces in cache
expect(viewMode.selected).toBe(cacheService.getPreferences().viewMode);
expect(analyticsService.sendAction).toHaveBeenCalledwith(
Constant.ACCOUNT_BALANCES.MODULE_NAME,
Constant.ACCOUNT_BALANCES,VIEW_SETTINGS,
[]
);
expect(analyticsService.sendAction).toHaveBeenCalledwith(
Constant.ACCOUNT_BALANCES.MODULE_NAME,
Constant.ACCOUNT_BALANCES,VIEW_SETTINGS,
[Constant.EXTD_MODE, Constant.NO_GROUPING]
);
});
Below are the errors:
Error: No response defined! In
../bower_components/angular-mocks/angular-mocks.js(line 1607) $httpBackend#/../bower_components/angular-mocks/angular-mocks.js:1607:63.

angularjs directive not being loaded when angularjs-dragula package is required

I am in the process of migrating our .NET Framework project over to .NET Core. And where we previously relied on the BundleTable tools in .NET Framework. We are now using webpack.
I have a directive that uses a package 'angularjs-dragula'. The webpack entry definition is as follows
'bundles/grouping':
[
"./Scripts/angularjs-dragula.js",
"./App/components/grid.directive.js",
"./App/components/inline-edit.directive.js",
"./App/services/grouping.service.js",
"./App/components/grouping/grouping.directive.js"
],
I initialize the directive as follows:
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
As it is, the page never loads grouping.directive. And there are no errors. Unless i remove the dragula file in the webpack entrypoint. The directive will then load, but complain:
ReferenceError: angularDragula is not defined[Learn More]
I have tried relying on webpack to import the package, and removed it from the entry definition. I installed angularjs-dragula into my node_modules, and used
var angularDragula = require('angularjs-dragula');
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
However this results in the same behavior.
The angularjs-dragula package works, since we were using it before the move to webpack. However now it seems to be silently failing, and taking the rest of the directive with it?
How can I begin to diagnose this issue?
The AngularJS wrapper for Dragula is unusual in that it places on global scope a function named angularDragula. That function registers the dragula module with AngularJS when the function is invoked with angular as an argument. It returns a string with the module name "dragula".
angularDragula(angular)
angular.module("app",["dragula"])
.run(function(dragulaService) {
console.log(dragulaService);
})
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angularjs-dragula/dist/angularjs-dragula.js"></script>
<body ng-app="app">
<h1>Hello AngularJS!</h1>
</body>
the page never loads grouping.directive
How can I begin to diagnose this issue?
I would use the Developer Console to insert breakpoints. Then examine variables.
The above example loads AngularJS with Dragula and successfully logs the dragularService.

Unit testing angular app with breezejs

I'm trying to setup unit tests with an Angular application that utilizes the breezejs library for odata queries. When running my tests with Karma the breeze library appears to attempt a configuration setup which I don't want to happen. I'm using angular mocks to mock the module but it appears the entityManagerFactory runs and tries to configure breeze. Here is the karma.conf setup
files: [
// 'www/Scripts/**/*.js',
// 'www/**/*.js',
'www/Scripts/angular.js',
'www/Scripts/angular-animate.min.js',
'www/Scripts/angular-translate.min.js',
'www/Scripts/angular-route.js',
'www/Scripts/angular-messages.js',
'www/Scripts/angular-sanitize.min.js',
'www/Scripts/angular-resource.js',
'www/Scripts/naturalSort.js',
'node_modules/angular-mocks/angular-mocks.js',
'www/Scripts/jquery-1.10.2.js',
'www/Scripts/breeze.min.js',
'www/Scripts/breeze.debug.js',
'www/Scripts/breeze.directives.js',
'www/Scripts/breeze.bridge*.js',
'www/app.module.js',
'www/data/**/*.js',
'www/core/**/*.js',
'www/blocks/**/*.js',
'www/common/**/*.js',
'www/features/**/*.js',
'test/unit/**/*Spec.js',
],
I get the following error when I run "karam start"
Error: Unable to initialize OData. Needed to support remote OData services
at Object.__requireLib [as requireLib] (www/Scripts/breeze.debug.js:410:11)
at webApiODataCtor.proto.initialize (www/Scripts/breeze.debug.js:16284:18)
at initializeAdapterInstanceCore (www/Scripts/breeze.debug.js:1874:14)
at Object.__config.initializeAdapterInstance (www/Scripts/breeze.debug.js:1795:12)
at configureBreeze (www/data/entityManagerFactory.js:46:41)
at Object.emFactory (www/data/entityManagerFactory.js:16:9)
at Object.invoke (www/Scripts/angular.js:4182:17)
at Object.enforcedReturnValue [as $get] (www/Scripts/angular.js:4035:37)
The entityManagerFactory calls a function (configureBreeze();) when its loaded to configure breeze, which must be the problem
function emFactory(breeze) {
configureBreeze();
var oldClient = null;
var factory = {
newManager: newManager,
serviceName: eCAT_ServiceName,
setAuthToken: setAuthToken
};
return factory;

Cannot get simple AngularJS Jasmine test to pass with Chutzpah

I have a very simple jasmine unit test that targets testing a simple operation on an AngularJS controller as follows:
/// <reference path="../src/jasmine.js"/>
/// <reference path="../../Scripts/angular.js"/>
/// <reference path="../../Scripts/angular-mocks.js"/>
/// <reference path="../../Scripts/angular-ui-router.js"/>
/// <reference path="../../Scripts/angular-route.js"/>
/// <reference path="../../Scripts/angular-resource.js"/>
/// <reference path="../../Scripts/angular-ui/ui-bootstrap.js"/>
/// <reference path="../../app/app.js"/>
/// <reference path="../../app/controllers/myController.js"/>
describe("my Controller", function () {
var scope, ctrl, vm;
beforeEach(module("app"));
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
ctrl = $controller(MyController, { $scope: scope });
vm = ctrl;
}));
it("sets the title", function() {
expect(vm.title).toBe("This is the title");
});
});
To begin the above test passes when using either of the following:
Open SpecRunner.html which contains the same references and displays a passed unit test in the jasmine default test runner
Test without modification passes if running via ReSharper test runner (this tool is not important other than to show the test passes using another test runner; the test isn't the culprit)
However no matter whenever I do any of the following using Chutzpah the test fails:
Run from the command line using chutzpah.console.exe
Use the right-click menu open in VS.NET to Run JS Tests
Each time the following error is given:
Error: [$injector:modulerr] Failed to instantiate module
app due to: [$injector:nomod] Module
'app' is not available! You either misspelled the
module name or forgot to load it. If registering a module ensure that
you specify the dependencies as the second argument.
So this is a very typical error if the AngularJS references are not included. However as you can see above they are for sure included and the other test runners see them and the test passes. The error is identical regardless if I run the unit test from the command line or if I view the output in VS.NET.
I even turned on the /trace parameter from the command line and viewed the chutzpah.log file. It sure enough is finding the Angular reference files so I'm not sure why the test is failing.
I've seen a ton of posts surrounding this and the solution is always that the references are missing. That's not the case here and I'm stuck. What am I missing to make this test pass using Chutzpah?
I recommend using a chutzpah.json settings file for angular projects. I placed mine at the root of my project, next to the web.config. You can specify the dependencies in one place this way, which is very helpful as the angular project grows rapidly. I can't know for sure, but I think yours would look something like the following:
{
"Framework": "jasmine",
"FrameworkVersion": "1",
"References": [
{ "Path": "./Scripts/angular/angular.js" },
{
"Path": "./Scripts/angular",
"Includes": [ "*.js" ]
},
{ "Path": "./Scripts/angular-ui/ui-bootstrap.js" },
{ "Path": "./app/app.js" },
{
"Path": "./app",
"Includes": [ "*.js" ]
}
],
"Tests": [
{ "Includes": [ "*.spec.js" ] }
]
}
This will run on jasmine version 1. I'm not sure how you It will include everything that matches "./Scripts/angular*.js" and everything that matches "./app/*.js" (including sub-directories). As you add new angular references and app modules, you should not need to modify this configuration (once you get it working).
I believe through thorough testing I have determined the cause. The issue is most likely that I'm using ES6 classes in my Angular .js files being used in my tests.
The issue is PhantomJS which Chutzpah uses does not support ES6 and the class keyword and thus it fails (see this for validation). I was able to reproduce in a non Angular sample. I used an old fashioned ES5 style IIFE and the simple test now passed. This is why it worked in Chrome and in ReSharper which used Chrome as the default test browser and Chrome supports the ES6 class keyword. If I make ReSharper use PhantomJS instead of Chrome, then my simple test also fails.
The root problem appears to be PhantomJS and its lack of support for ES6 syntax.
Here is a blog post I wrote on my findings after pulling my hair out on this for a couple of weeks. It explains more in detail about the issues with writing non-ES5 complaint code and using that with Chutzpah and PhantomJS:
Chutzpah and non-ES5 JavaScript for Unit Testing is Problematic

Displaying Test Result Summary with Protractor

I have an AngularJS app that I am using end-to-end testing on. This app relies on Protractor and Jasmine for testing. I'm running my tests via a Grunt task.
Does anyone know of a task or a way to display a summary of Protractor's test results in the command line? Currently, I have time-grunt to display a summary of how long each task took. I'd love to have the ability to show something like 'Ran [x] tests. [y] Succeeded. [z] Failed.'
Thank you
You can add a consoleReporter. It's a little more verbose, but it does give a summary at the end.
Using jasmine-reporters you can add several reporters. My favorite is the HtmlReporter that takes screenshots when the test fails. Below is an example of several reporters configured in the protractor.conf.js
onPrepare: function () {
require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter('reports', true, true));
jasmine.getEnv().addReporter(new jasmine.ConsoleReporter());
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: 'reports/screenshots' ,
takeScreenShotsOnlyForFailedSpecs: true
}));
},
If you want to tweak what you display in the console you can use jasmine-spec-reporter:

Resources