UI-router interfiere con htt httpbackend unit test, angular js


Este es un controlador con una función submit:

$scope.submit = function(){   

 $http.post('/api/project', $scope.project)
      .success(function(data, status){
        $modalInstance.dismiss(true);
      })
      .error(function(data){
        console.log(data);
      })
  }
}

Esta es mi prueba

it('should make a post to /api/project on submit and close the modal on success', function() {
    scope.submit();

    $httpBackend.expectPOST('/api/project').respond(200, 'test');

    $httpBackend.flush();

    expect(modalInstance.dismiss).toHaveBeenCalledWith(true);
  });

El error que obtengo es:

Error: Unexpected request: GET views/appBar.html

Vistas / AppBar.html es mi plantilla:

 .state('project', {
    url: '/',
    templateUrl:'views/appBar.html',
    controller: 'ProjectsCtrl'
  })

Así que de alguna manera ui-router está haciendo que mi point httpBackend apunte a esto en lugar de mi función submit. Tengo el mismo problema en todas mis pruebas con $httpBackend.

¿Hay alguna solución a esto?

Author: Joe, 2014-05-14

5 answers

Tome esta esencia https://gist.github.com/wilsonwc/8358542

angular.module('stateMock',[]);
angular.module('stateMock').service("$state", function($q){
    this.expectedTransitions = [];
    this.transitionTo = function(stateName){
        if(this.expectedTransitions.length > 0){
            var expectedState = this.expectedTransitions.shift();
            if(expectedState !== stateName){
                throw Error("Expected transition to state: " + expectedState + " but transitioned to " + stateName );
            }
        }else{
            throw Error("No more transitions were expected! Tried to transition to "+ stateName );
        }
        console.log("Mock transition to: " + stateName);
        var deferred = $q.defer();
        var promise = deferred.promise;
        deferred.resolve();
        return promise;
    }
    this.go = this.transitionTo;
    this.expectTransitionTo = function(stateName){
        this.expectedTransitions.push(stateName);
    }

    this.ensureAllTransitionsHappened = function(){
        if(this.expectedTransitions.length > 0){
            throw Error("Not all transitions happened!");
        }
    }
});

Agréguelo a un archivo llamado stateMock en su carpeta de prueba/simulacro, incluya ese archivo en su configuración de karma si aún no está recogido.

La configuración antes de su prueba debería ser algo como esto:

beforeEach(module('stateMock'));

// Initialize the controller and a mock scope
beforeEach(inject(function ($state //other vars as needed) {
    state = $state;
    //initialize other stuff
}

Luego en su prueba debe agregar

state.expectTransitionTo('project');
 48
Author: rosswil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-14 07:02:44

Este problema de Github sobre Unit Testing UI Router explica más detalladamente lo que está sucediendo.

El problema es que $httpBackend.flush() activa una emisión que luego activa el caso de lo contrario de la stateProvider.

Una solución simple puede ser hacer la siguiente configuración, como mencionó @darinclark en el hilo de Github mencionado anteriormente. Esto es válido si no necesita probar transiciones de estado. De lo contrario, echa un vistazo a la respuesta de@rosswil que está inspirada en la respuesta de@Vratislav en Github .

beforeEach(module(function ($urlRouterProvider) {
    $urlRouterProvider.otherwise(function(){return false;});
}));

EDITADO

Gracias a Chris T para informar de esto en los comentarios, parece después de v0.2.14? la mejor manera de hacer esto es usar

beforeEach(module(function($urlRouterProvider) {
  $urlRouterProvider.deferIntercept();
}));
 39
Author: Ronan Quillevere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:32:27

Si no desea agregar archivos gist como dice en la solución correcta, puede agregar una condición" when " a su condition httpBackend para ignorar las peticiones GET de vistas como esta:

$httpBackend.when("GET", function (url) {
    // This condition works for my needs, but maybe you need to improve it
    return url.indexOf(".tpl.html") !== -1;
}).passThrough();
 3
Author: Jose Ignacio Hita,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-22 10:29:37

Tengo el mismo error que tu comentaste, después de un servicio de llamada me preguntan por la url de lo contrario ui-route.

Para resolver el problema de llamar a la de otro modo ui-route en testing es no inyectar state state en antes de cada estado. En mis pruebas state estado no tiene sentido usarlo.

 2
Author: Alex Carod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-01 08:42:05

Mueva sus servicios a su propio módulo que no depende de la interfaz de usuario.router. haga que su aplicación principal dependa de este módulo. Cuando pruebe no pruebe la aplicación principal, pruebe el módulo que tiene sus servicios en ella. El stateprovider no intentará cambiar estado / ruta porque este módulo no sabe nada sobre la interfaz de usuario.router. Esto funcionó para mí.

 1
Author: Maccurt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-20 11:57:01