3

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.

Bennett McElwee
  • 24,740
  • 6
  • 54
  • 63
Andrea Reginato
  • 1,338
  • 1
  • 17
  • 23

1 Answers1

1

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.

Community
  • 1
  • 1
Andrea Reginato
  • 1,338
  • 1
  • 17
  • 23
  • So do I need to replicate all the app's existing html in this new test html file? Is there a way just to include the $httpBackend in the e2e test as we can in the unit test, without making modifications to the actual app? – EdL Jul 31 '13 at 10:46
  • To answer my own question - if all your html is in one file and you're not using routing and partial templates, then yes, you would need to duplicate your html file to have a test version. You don't need to alter your app.js, you can just add a test-app.js that includes the ngMockE2E. Currently it does not seem possible to only modify scenario.js. Best example I've found: https://github.com/stephennancekivell/angular_e2e_http/tree/ngMockE2E – EdL Jul 31 '13 at 11:22