web-dev-qa-db-fra.com

TypeError: undefined n'est pas un constructeur

Je suis très nouveau sur Angular et j'essaie de résoudre une bonne partie de ces problèmes. J'écris des tests avec Angular 1.5.8 qui J'ai généré à partir du générateur Yeoman.

Plus précisément, j'essaie de comprendre comment manipuler les résultats de $ httpBackend (je ne suis pas sûr que ce soit important ou non) ...

Dans mon fichier app.js, j'ai le code suivant:

.run(['$rootScope', '$location', 'breadcrumbService', function ($rootScope, $location, breadcrumbService) {
    $rootScope.$on('$viewContentLoaded', function () {
        jQuery('html, body').animate({scrollTop: 0}, 200);
    });

    $rootScope.isEditMode = false;
    $rootScope.$on('$stateChangeSuccess', function () {
        // ------------ this next line is failing -----------
        $rootScope.isEditMode = $location.path().toLowerCase().endsWith('/edit') || $location.path().toLowerCase().endsWith('/new');
    });

    $rootScope.parseJson = function (value) {
        return angular.fromJson(value);
    };

    $rootScope.bc = breadcrumbService;

    $rootScope.title = "";
}])

La ligne à peu près à mi-chemin (où j'ai ajouté le commentaire) échoue. Plus précisément, la fonction endsWith échoue (toLower va bien), avec cette erreur:

PhantomJS 2.1.1 (Windows 8 0.0.0) Service: breadcrumbService should return breadcrumb label in json format FAILED
        TypeError: undefined is not a constructor (evaluating '$location.path().toLowerCase().endsWith('/edit')') in app/scripts/app.js (line 44)
        app/scripts/app.js:44:72
        $broadcast@bower_components/angular/angular.js:18005:33
        bower_components/angular-ui-router/release/angular-ui-router.js:3353:32
        processQueue@bower_components/angular/angular.js:16383:30
        bower_components/angular/angular.js:16399:39
        $eval@bower_components/angular/angular.js:17682:28
        $digest@bower_components/angular/angular.js:17495:36
        $apply@bower_components/angular/angular.js:17790:31
        done@bower_components/angular/angular.js:11831:53
        handleResponse@bower_components/angular-mocks/angular-mocks.js:1368:17
        flush@bower_components/angular-mocks/angular-mocks.js:1808:26
        test/spec/services/breadcrumbservice.js:33:27
        invoke@bower_components/angular/angular.js:4718:24
        workFn@bower_components/angular-mocks/angular-mocks.js:3085:26

Voici mon code de test (une ordure modifiée à partir de différents exemples - essayant juste de la faire fonctionner):

'use strict';

describe('Service: breadcrumbService', function () {

    // load the service's module
    beforeEach(module('myModule'));

    var $httpBackend, $rootScope, createController, authRequestHandler;
    beforeEach(inject(function($injector) {

        $httpBackend = $injector.get('$httpBackend');
        console.log('Is null? '+ ($httpBackend == null));
        $httpBackend.whenGET(/views\/.*/).respond(200, [{}, {}, {}]);

        authRequestHandler = $httpBackend.when('GET', '/api/v1/SiteStagings')
            .respond({userId: 'userX'}, {'A-Token': 'xxx'});

        // Get hold of a scope (i.e. the root scope)
        $rootScope = $injector.get('$rootScope');
        $httpBackend.flush();
    }));

    // instantiate service
    var breadcrumbService;
    beforeEach(inject(function (_breadcrumbService_) {
        breadcrumbService = _breadcrumbService_;
    }));

    it('svc should exist', function () {
        expect(!!breadcrumbService).toBe(true);
    });

    it('should return breadcrumb label in json format', function () {
        var result = breadcrumbService.getFromCache('site', 'SiteGroupStagings', 46, 'SiteGroupDesc');
        console.log(result);
        expect(!!result).toBe(true);

    });
});

Je ne doute pas que je fais quelque chose de mal ici, je ne peux tout simplement pas comprendre ce que c'est. Qu'est-ce que cette erreur signifie réellement et pourquoi cela ne ressemble-t-il pas à mon appel à endsWith?

Merci

31
Adam Plocher

undefined n'est pas un constructeur

est un message d’erreur que PhantomJS s’affiche lorsque vous avez essayé d’appeler une fonction non définie. Cela dépend de la version de ECMAScript prise en charge par votre PhantomJS. Comme vous l'avez dit, cela fonctionne bien dans Chrome, car ce navigateur prend en charge la fonction que vous utilisez dans test. Pour résoudre votre problème et pouvoir continuer à utiliser PhantomJS, vous pouvez remplacer la fonction "Inconnu par PhantomJS" par la vôtre.

55
dgraf

J'obtenais l'erreur TypeError: undefined is not a constructor En utilisant la méthode includes(). Les méthodes includes() et endsWith() sont nouvelles dans ECMAScript 2015 et ne sont pas prises en charge dans Internet Explorer, et évidemment pas par PhantomJS.

Il est possible que votre utilisateur final utilise Internet Explorer. Dans ce cas, vous pouvez utiliser la méthode indexOf() entièrement prise en charge au lieu de includes() ou endsWith().

Par exemple, dans mon cas, tout fonctionnait parfaitement en chrome, mais mes tests échouaient:

if (item.name.includes('contents'))

J'ai changé pour utiliser la méthode indexOf () à la place:

if (item.name.indexOf('contents') !== -1)

Et puis je ne recevais plus l'erreur

TypeError: undefined n'est pas un constructeur

15
Hula_Zell

J'ai débattu de l'opportunité de poster ceci comme réponse ou comme simple modification de ma question, mais je suppose que c'est ma réponse (pour l'instant):

Il semble que le problème soit lié à PhantomJS. Dès que j'ai changé le moteur en Chrome dans le fichier karma.conf.js, ces tests ont abouti.

Je ne sais toujours pas ce que ce message d'erreur est censé signifier et pourquoi cela ne fonctionnait pas avec PhantomJS, mais au moins je suis maintenant capable de continuer.

Voici les modifications apportées à mon karma.conf.js (au cas où quelqu'un serait curieux):

browsers: [
 //'PhantomJS',
 'Chrome'
],

// Which plugins to enable
plugins: [
 'karma-chrome-launcher',
 //'karma-phantomjs-launcher',
 'karma-jasmine'
],

Btw - J'ai remarqué que endsWith est nouveau dans ECMAScript6 (je pensais qu'il était plus ancien), mais WebStorm montre qu'il fait référence à une fonction d'assistance dans angular-ui-grid. J'ai passé un bon bout de temps à bricoler le tableau files du fichier karma.conf.js pour tenter de voir si la dépendance de la grille ui se chargeait trop tard ou autre chose. Dans tous les tests, cela a bien fonctionné dans Chrome mais pas PhantomJS. Je ne sais toujours pas pourquoi.

10
Adam Plocher

Dans mon cas: dépendances cycliques:

PhantomJS 2.1.1 (Windows 8 0.0.0) ERREUR TypeError: undefined n'est pas un constructeur (évaluation '(0, _actions.prefix) (' SET_USER_INPUT_PHONE_NUMBER ')' à undefined: 12

J'ai eu la même erreur après avoir ajouté des importations dans mon code de production javascript (syntaxe ES6 compilée avec babel/webpack). Les modifications étaient correctes quand une version de production de l'application a été chargée dans chrome mais l'exécution des tests avec phantomJS a généré l'erreur. Dans mon cas, les importations ajoutées ont créé des dépendances cycliques.

Je laisse tomber ceci ici pour référence future (je suis tombé sur le même problème il y a quelques semaines et je ne veux plus me gratter la tête dans quelques semaines) et pour d'autres qui recherchent la même erreur sur Google.

6
Martin

J'ai rencontré une erreur similaire avec PhantomJS:

Pour moi, l'erreur était la façon dont je créais un objet espion pour mon service.

Erreur en ligne dans le fichier de code new Service.getData(param1, param2)

Correction dans le fichier de test: jasmine.createSpyObj('Service',['getData'])

Ce qui manquait, c'était d'ajouter ['getData] lors de la création de spyObj

0
Alok