Andrea Reginato
Andrea Reginato

Reputation: 1338

Angular.js e2e test HTTP requests to external service

I'm trying to make some basic tests on directives on an e2e scenario. The code works just fine and I can render the new element to the browser. Here the code I'm using.

Here the directive code.

'use strict';

var directives = angular.module('lelylan.directives', [])

directives.directive('device', ['Device', function(Device) {
  var definition = {
    restrict: 'E',
    replace: true,
    templateUrl: 'js/templates/device.html',
    scope: { id: '@' }
  };

  definition.link = function postLink(scope, element, attrs) {
    scope.$watch('id', function(value){
      var device = Device.get({ id: scope.id }, function() {
        scope.device = device;
      });
    });
  };

  return definition
}]);

Here the Device service code.

// Service Device
'use strict';

angular.module('lelylan.services', ['ngResource']).
  factory('Device', ['$resource', '$http', function($resource, $http) {

    var token = 'df39d56eaa83cf94ef546cebdfb31241327e62f8712ddc4fad0297e8de746f62';
    $http.defaults.headers.common["Authorization"] = 'Bearer ' + token;

    var resource = $resource(
      'http://localhost:port/devices/:id',
      { port: ':3001', id: '@id' },
      { update: { method: 'PUT' } }
    );

    return resource;
  }]);

Here the app code.

'use strict';

angular.module('lelylan', ['lelylan.services', 'lelylan.directives'])

And here the index.html.

<!doctype html>
<html lang="en" ng-app="lelylan">
  <head>
    <meta charset="utf-8">
    <title>Lelylan Components</title>
    <link rel="stylesheet" href="css/app.css"/>
  </head>
  <body>

    <device id="50c61ff1d033a9b610000001"></device>

    <!-- In production use: <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script> -->
    <script src="lib/angular/angular.js"></script>
    <script src="lib/angular/angular-resource.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/directives.js"></script>
  </body>
</html>

After reading the Angular documentation and trying different solutions I came up with the following test where I try mock my Backend requests. The problem is that the request still hits the real service. It looks like I'm not able to intercept the requests.

// e2e test
'use strict';

describe('directives', function() {

  var resource = { id: '1', uri: 'http://localhost:3001/devices/1' };
  var myAppDev = angular.module('myAppDev', ['lelylan', 'ngMockE2E']);

  myAppDev.run(function($httpBackend) {
    $httpBackend.when('GET', 'http://localhost:3001/devices/1').respond(resource);
    $httpBackend.when('GET', /\/templates\//).passThrough();
  });

  beforeEach(function() {
    browser().navigateTo('../../app/index.html');
  });

  describe('when renders a device', function() {

    it('renders the title', function() {
      expect(element('.device .name').text()).toEqual('Closet dimmer');
    });

    it('renders the last time update', function() {
      expect(element('.device .updated-at').text()).toEqual('2012-12-20T18:40:19Z');
    })
  });
});

I think I'm missing some configurations, but I can't really understand which ones. Thanks a lot.

Upvotes: 3

Views: 3590

Answers (1)

Andrea Reginato
Andrea Reginato

Reputation: 1338

Reading the the last comment in this question I came with the final solution.

Actually I was missing one important step, due to the fact that I had to use an HTML file that uses the mocked application. Let's make the code speak.

1) I've created an HTML file with the test environment. The main difference is related to the fact that I've set the ng-app=test and I've added two new JS files. The first is /test/e2e/app-test.js and is where I've created the test module and the second is /test/lib/angular-mocks.js.

<!doctype html>
<html lang="en" ng-app="test">
  <head>
    <meta charset="utf-8">
    <title>Lelylan Test</title>
    <link rel="stylesheet" href="css/app.css"/>
  </head>
  <body>

    <device id="1"></device>

    <script src="lib/angular/angular.js"></script>
    <script src="lib/angular/angular-resource.js"></script>
    <script src="js/app.js"></script>
    <script src="js/settings.js"></script>
    <script src="js/services.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/filters.js"></script>
    <script src="js/directives.js"></script>

    <!-- Test application with mocked requests -->
    <script src="../test/e2e/app-test.js"></script>
    <script src="../test/lib/angular/angular-mocks.js"></script>
  </body>
</html>

Now, lets see how we implement the test module. In here I define a module that is exactly as my main module (lelylan), with the addition of ngMockE2E that lets you access to $httpBackend and mock the HTTP requests.

'use strict';

var resource = { id: '1', uri: 'http://localhost:3001/devices/1' };

var test = angular.module('test', ['lelylan', 'ngMockE2E']);

test.run(function($httpBackend) {
  $httpBackend.when('GET', 'http://localhost:3001/devices/1').respond(resource);
  $httpBackend.when('GET', /\/templates\//).passThrough();
});

Nothing more. Run scripts/e2e-test.sh and you're done.

Upvotes: 1

Related Questions