Understanding Selenium + browsermob-proxy + protractor + AngularJS - angularjs

What I have: several integration test specs written in Jasmine for my AngularJS app (they navigate through my entire app)
What I want: perform a network monitoring of my app and export the data using HAR
Naive solution: just write a script which receives an URL and export the data using HAR. It's easy, but it's not automatic (I need to provide the urls manually)
Enhance solution: automate the process mentioned. A script that navigates through all the pages of my app and extracts the network data for each. But since I'm already navigating through all the pages of my app via integration tests (protractor + Jasmine) I want to just "plug-in" the part about exporting the network traffic.
I've found this How can I use BrowserMob Proxy with Protractor?, and I was checking out the example provided here example, but I'm not quite sure how it works.
What I should put as the host and port for the proxy?
I'm using Selenium, and I've specified the host and port for it, but I'm getting ECONNREFUSED errors.
This is my protractor file config:
var Proxy = require('browsermob-proxy').Proxy;
...
protractorConf = exports.base = {
//... more things
onPrepare: function() {
... more things....
browser.params.proxy = new Proxy({ // my selenium config for browsermob
selHost: '10.243.146.33',
selPort: 9456
});
//... more things
}
}
And in one of my integration tests specs (it's CoffeeScript btw):
beforeEach ->
browser.get BASE_URL
browser.params.proxy.doHAR 'some/page/of/my/app', (err, data) ->
if err
console.log err
else
console.log data
But I'm getting as I've said ECONNREFUSED error. I'm quite lost about the integration about Selenium with Protractor and brosermob.
Any ideas or alternatives? Thanks!

Related

Setting environment for AngularJS development with existing OSGi/Rest serverices

How to setup the dev environment where the UI is to be re-done using AngularJS and typescript etc but we already have an existing set of services hosted in rest/osgi bundles.
All the development models with AngularJS and type script talks about node/npm etc but how do we hit existing services with that? do i need to enable cors etc for development?
how is UI development done in these kind of projects as i believe not all projects are done from the beginning and have liberty to use node at server.
Well, usually from an angular app you define some kind of angular service that talks to your api in a standard way.
It's true that most "Frontend" projects use a mocking server during development but it isn't hard to hard to use a real server for this, provided it's not you own production server, obviously.
About the cors issue, I use to let CORS fully open during development ,and have a minimally accesable configuration on production, depending on your project.
After some research we have finalized the DevEnv and it's working out very well.
used angular cli for development
used proxy server to make the calls made to 4200 port to redirect to express server running at port 3000
package.json:
"start": "ng serve --proxy-config proxy.conf.json",
finally wrote a small express server to login to existing server and then pipe all requests!
This was our code:
var app = express();
//enable cors
var cors = require('cors')
app.use(cors());
//relay all calls to osgi server!!
app.use('/a/b/c/rest', function (req, res) {
var apiServerHost = "https://" + HOST + ":" + PORT + "/a/b/c/rest";
try {
var url = apiServerHost + req.url;
req.pipe(request(
{
headers: headers,
url: url,
"rejectUnauthorized": false
})).pipe(res);
} catch (error)
{
console.log("Error " + error);
}
} // Added by review
No mock required

A second node server (or port) won't start in production (Elastic Beanstalk)

I have a Node/Angular app I'm trying to deploy. It uses two node servers: One to essentially serve the app; another to get data from an API, when a specific port is requested by the app, and store that data locally.
I've got it working perfectly on my own local machine. However, when I deploy to production environments -- either Heroku or AWS Elastic Beanstalk -- I find that the second script either won't run or won't start properly. The end result is, it doesn't get the data I need.
Here are the two scripts; they're both set to run in package.json under "start": "node main.js & node node-server.js"
main.js (again, this one seems to be serving the app just fine):
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/app'));
app.listen(process.env.PORT || 3000);
node-server.js (the one that doesn't seem to work; no data is gathered or populated in the app):
var http = require('http');
var port2 = 1234
var fs = require('fs');
//We need a function which handles requests and send response
function handleRequest(req, res) {
request.get({
url: 'http://sample-url.json',
qs: {
url: 'http://sampletool/pb/newsletter/?content=true'
}
}, function (err, result) {
res.end(result.body);
fs.writeFile('app/data.json', result.body, function (err) {
if (err) return console.log(err);
console.log('API data > data.json');
});
});
}
//Create a server
var server = http.createServer(handleRequest);
//Lets start our server
server.listen(port2, function () {
//Callback triggered when server is successfully listening. Hurray!
console.log("Server listening on: http://0.0.0.0:%d", port2);
});
Then, the main Angular app calls this port (http://0.0.0.0:1234) when the page is loaded, to request new data.
Elastic Beanstalk is using nginx, something I'm not super familiar with and that I don't have running on my local.
Is there something big I'm missing in configuring multiple node.js servers to be running on different ports in a production environment? Thanks in advance for any help.
For security reasons, cloud service providers typically allow the usage of only one port (which is dynamically and randomly assigned to the PORT environment variable) for an application to use from a node server. Read this section from Heroku documentation to understand more about this.
This is why the main app (main.js) that uses process.env.PORT is working and the other app (node-server.js) that uses hard-coded 1234 is not.
This question has some pointers about the feasibility of multiple ports on Heroku (though, there is no good news there, I am afraid).
As how to go about fixing this, one thing that could be tried is to split this into two separate apps that are deployed separately with separate package.json etc.

AngularJS better way to read config file?

I built a angularJS app that I wanted dynamically configured, so I created a config.json file with the needed configurations, and decided to load the config file in app.config as such:
angular.module("myapp",[]).config([ my injections] , function(my providers){
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("GET","config.json"); //my config file
xhr.send();
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200)
{
//config file parsed, set up params
}
}
})
The reason I am doing it this way is because $http is not injected in config state, and I do not want to "configure" the app at a controller level.
The application works fine. it does what I want to do, and everything works great...EXCEPT when it comes to unit testing (with karma + jasmine).
even though in karma.conf i have:
{pattern: 'config.json',served:true,watched:false,included:false}
defined, when I launch karma, I get a cli [WARN] about config.json 404. and my unit tests to see if everything is configured, fails (i.e it didnt read config.json)
Is there a better way to write config files for unit testing?
In our apps we have external file config.js, which contains just ordinary module which provides constants with configuration.
angular.module('myAppPrefixconfig')
.constant('PLAIN_CONSTANT', 'value'),
.constant('APP_CONFIG', {...});
In your app you have dependancy on it, and there is ordinary http request - which can be resolved by your backend with proper configuration.
In Karma tests you can then provide 'testing config' directly in karma.conf.

Timed out waiting for Protractor to synchronize -- happens on server, but not on localhost

I'm writing a suite of Protractor tests from the ground up for a new Angular webapp. My team has asked me to run my tests against their Test server instance. I've got my config file and a basic test spec set up, but as soon as I hit the main page and do a simple expect() statement, I get "Timed out waiting for Protractor to synchronize with the page after 11 seconds."
Here's my test:
describe('the home page', function() {
it('should display the correct user name', function(){
expect(element(by.binding('user.name')).getText()).toContain(browser.params.login.user);
});
});
I cloned the dev team's git repo, set it up on my localhost, changed my baseUrl and ran my Protractor test against it locally. Passed without a hitch.
After some conversation with the dev team, I've determined that it's not a $http or $timeout issue. We use both of those services, but not repeatedly (I don't think they're "polling"). None of them should happen more than once, and all the timeouts are a half-second long.
What else could cause Protractor to time out like that? I wish it failed on my localhost so I could go tweak the code until I find out what's causing the problem, but it doesn't.
I have discovered the solution: check for console errors.
Turns out, one of our $http requests wasn't coming back because my Protractor tests were accessing the page via https, but one of our xhtml endpoints was at a non-secured location. This resulted in a very helpful console error which I had not yet seen, because it only occurred when accessing the site with WebDriver.
The error text: "The page at [url] was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint. This request has been blocked; the content must be served over HTTPS."
I modified my baseUrl to access the site via regular http, and now everything is working fine.

$httpbackend from ngMockE2E never called

I'm trying to make some backendless e2e tests, so I need to mocks API calls.
Here is what I did:
angular.module('foo.bar.e2eConf', ['foo.bar', 'ngMockE2E']).
run(function($httpBackend) {
$httpBackend.whenGET('/foo/bar').respond({foo:'bar'});
});
Then I configured my conf/karma.e2e.conf like this (pathes are ok):
var basePath = '../';
var files = [
ANGULAR_SCENARIO,
ANGULAR_SCENARIO_ADAPTER,
// bower libs
'components/angular/index.js',
'components/jquery/jquery.js',
'components/angular-resource/index.js',
'components/angular-mocks/index.js',
'components/chai/chai.js',
'test/chai.conf.js',
'src/app/**/*.js',
{pattern:'src/app/**/partials/*.tpl.html', included:false},
'test/e2e/**/*.js'
];
var singleRun = false;
var browsers = ['Chrome'];
var proxies = {'/': 'http://localhost:8000/'};
I can run tests that doesn't involve API calls, but when I run a test that involves it I get a nice Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:9876/foo/bar
I guess I misconfigured some stuff, but I can't figure out what??
Is there a conflict between the proxy and the mock? i.e. proxying /foo/bar to http://localhost:8000/foo/bar instead of using the mock?
Any idea?
Regards
Xavier
You need to create a version of your app that bootstraps off the foo.bar.e2eConf module, instead of bootstrapping off the foo.bar module.
You'll have to include the javascript files angular-mocks.js and the new module you defined above in your app index page.
You should be able to test this outside Karma by just using this new app and seeing it return data from your mocks.
You probably don't need to add half those files to the Karma configuration. That's just for adding files to the testing scenario.. its going to load your app in an iframe and your app is responsible for loading it's own javascript.
I'm using php to server up either version of the app depending on what URL I use: either the real version that uses the api calls, or the e2e version that uses the mocks.

Resources