Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing AngularFire karma error

I am getting this error when I run my karma unit script and I haven't been able to figure out why

Error: [$injector:unpr] Unknown provider: FBURLProvider <- FBURL

Here is my directive code

'use strict';

angular.module('userMenu', ['firebase'])
  .directive('userMenu', function (FBURL, angularFire) {
    return {
      restrict: 'A',
      scope: true ,
      link: function postLink(scope, element, attrs) {

        /**
         * Returns the logged in user information
         * @param {string} FBURL
         * @param {object} scope
         * @returns {promise}
         */
        scope.getUserDataFromFirebase = function(FBURL, scope) {
          var ref = new Firebase(FBURL + '/users/' + scope.auth.id);
          return angularFire(ref, scope, 'user', {})
        }

      }
    };
  });

Here is my spec code

'use strict';

describe('Directive: userMenu', function () {

  // load the directive's module
  beforeEach(module('userMenu', 'firebase'));

  var element,
    elementScope,
    scope;


  beforeEach(inject(function ($rootScope, $compile, _FBURL_, _angularFire_) {
    scope = $rootScope.$new();
    element = angular.element('<div user-menu></div>');
    element = $compile(element)(scope);
    elementScope = element.scope();
  }));

  it('should get user data', inject(function ($compile) {
    console.log(scope);
  }));
});

To be honest I'm not that familiar with unit testing so I'm probably missing something really obvious but any help would be appreciated.

like image 651
Paul Sheldrake Avatar asked Dec 06 '25 00:12

Paul Sheldrake


2 Answers

If everything is working in your app, but you're getting an error in your tests, then you need to add firebase to the Karma's files. Find your karma.conf.js (in yeoman generated ionic-angular add this to the Karma suite of Gruntfile.js), and have it resemble the following:

karma: {
  options: {
    ...
    files: [
      ...
      'https://cdn.firebase.com/v0/firebase.js',
      'app/bower_components/angular-fire/angularFire.js',
      ...
    ],
    ...
  }
  ...
}

Then in your spec, include firebase:

beforeEach(module('Simplift', 'firebase'));

And every time you need to use the firebase service:

describe/it('some test desc ...', inject(function (..., $firebase) {
  // now we can use $firebase!!
  fireSync = $firebase(new Firebase('https://app_name.firebaseio.com'));
  ...
}));

Took me forever to figure this out, and hoping it will alleviate stress for someone. This works for me for now, but probably not the cleanest way to do it (please contribute suggestions!), since you're not actually stubbing out the firebase data, but you could add a 'test' url to your firebase DB.

like image 154
delisdeli Avatar answered Dec 08 '25 14:12

delisdeli


The Firbase team had pointed me in the direction of some testing code in the Fireseed project that has subsequently been removed. Here is my unit test that includes the stubs that were in the Fireseed project

'use strict';

describe('Directive: userMenu', function () {

  // load the directive's module
  beforeEach(module('userMenu', 'firebase', function($provide) {
    $provide.value('Firebase', firebaseStub());
    $provide.value('FBURL', 'FAKE_FB_URL');
    $provide.value('angularFireAuth', angularAuthStub());
  }));


  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function stub() {
    var out = {};
    angular.forEach(arguments, function(m) {
      out[m] = jasmine.createSpy();
    });
    return out;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function stub() {
    var out = {};
    angular.forEach(arguments, function(m) {
      out[m] = jasmine.createSpy();
    });
    return out;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function reject($q, error) {
    var def = $q.defer();
    def.reject(error);
    return def.promise;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function resolve($q, val) {
    var def = $q.defer();
    def.resolve(val);
    return def.promise;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function firebaseStub() {
    // firebase is invoked using new Firebase, but we need a static ref
    // to the functions before it is instantiated, so we cheat here by
    // attaching the functions as Firebase.fns, and ignore new (we don't use `this` or `prototype`)
    var fns = stub('set');
    customSpy(fns, 'child', function() { return fns; });

    var Firebase = function() {
      angular.extend(this, fns);
      return fns;
    };
    Firebase.fns = fns;

    return Firebase;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function angularAuthStub() {
    var auth = stub('login', 'logout', 'createAccount', 'changePassword');
    auth._authClient = stub('changePassword', 'createUser');
    return auth;
  }
  /**
   * This is from https://github.com/firebase/angularFire-seed/blob/master/test/unit/servicesSpec.js
   */
  function customSpy(obj, m, fn) {
    obj[m] = fn;
    spyOn(obj, m).andCallThrough();
  }

  var element,
    elementScope,
    scope;


  beforeEach(inject(function ($rootScope, $compile) {
    scope = $rootScope.$new();
    element = angular.element('<div user-menu></div>');
    element = $compile(element)(scope);
    elementScope = element.scope();
  }));

  it('should default to a login message', inject(function ($compile) {
    scope.$digest();
    var text = element.text();
    expect(text).toBe('Please login');
  }));

  it('default message should contain a link to login page', inject(function ($compile) {
    scope.$digest();
    var href = element.find('a').attr('href');
    expect(href).toBe('#/login');
  }));
});
like image 40
Paul Sheldrake Avatar answered Dec 08 '25 16:12

Paul Sheldrake



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!