title: Jasmine won't test an angular service with multiple nested promises
body: <p>I'm trying to write a jasmine test case for an angular service. Since I have to do calls to a PouchDB and fetch http ressources, I use $q. </p>
  
  <p>In my application I have two datasource : the PouchDB as localStorage and an XML document that is requested through http. I managed to write test for both localStorage.service and XMLparser.service without to much trouble (I had to do a 50ms timeout then a call to $rootScopre.$digest()).</p>
  
  <p>However, when i try to run tests for the service that uses localStorage and XMLParser, I just can't make it pass. Karma hangs for 5 sec and the test fails at timeout. If I add some console.log() everywhere, all the code is actually executed. It's like if done() was not closing the test case. If I run the code directly in my application it works.</p>
  
  <p>There's a lot going on in my code so I'll try to explain : </p>
  
  <pre><code>function loadCategories(){
      var deferred = $q.defer();
  
      //Json structure that tells my parser what to extract from the XML
      var structure = { ... } 
  
      //Check in the PouchDB to see if the structure is already cached
      localStorage.getStructure() 
      .then(function(struct){
          deferred.resolve(struct.category);
      })
      .catch(function(e){
          if(e.name != 'not_found') return deferred.reject(e);
  
          //If the structure is not cached, get it from the parser through an http request
          xmlparser.readFile(apiUrl, structure) 
          .then(function(doc){
              localStorage.saveStructure(doc); //Save it in the PouchDB
              deferred.resolve(doc.category); //Resolve with the categories
          })
          .catch(function(e){
              deferred.reject(e);
          });
      });
  
      return deferred.promise;
  }
  </code></pre>
  
  <p>Here's how I'm testing it :</p>
  
  <pre><code>it('should list the categories', function(done){
      //The answer to this call is mocked in the beforeEach
      $httpBackend.expectGET('/lib/xmlDocuments/indicator.xml');
  
      var promise = Indicator.getCategories()
      .then(function(categories){
          expect(categories[0].name).toBe('Emplois par secteur d\'activité');
          expect(categories[1].name).toBe('Emplois par niveau de compétence');
          done();
          //When i put a console.log here it get executed...
      })
      .catch(function(e){
          expect(e).toBe(null);
      });
  
      //Here i tryed to force a $digest and then flush() the requests
      //but i still get "Async callback was not invoked within timeout"
      setTimeout(function() {
          $scope.$digest();
          setTimeout(function(){
              $httpBackend.flush();
          }, 50);
      }, 50);
  });
  </code></pre>
  
  <p>Now I'm pretty sure that there's something that I'm not doing properly but I can't put my finger on it :</p>
  
  <ul>
  <li>Am I missusing the promisses?</li>
  <li>Should I mock XMLParser and localStorage?</li>
  <li>Is there an error in my jasmine?</li>
  <li>Do I over use $q?</li>
  </ul>
  
  <p>Thanks for your help!</p>