web-dev-qa-db-fra.com

Variables globales dans le lanceur de test Karma

J'ai une variable globale définie dans mon modèle principal, que j'utilise pour stocker des bits d'information de l'arrière-plan, tels que le chemin du contexte de l'environnement. Je ne peux pas déplacer cette variable dans un service.

Comment puis-je exposer cette variable à Karma lorsque j'exécute les tests unitaires?

34
Mimo

Vous déclarez cette variable globale dans votre fichier de test:

var global = "something";

describe('Your test suit', function() {
...
});

ou ajoutez un fichier Javascript où il est défini à votre karma.conf.js fichier:

// list of files / patterns to load in the browser
files: [
   ...,
   'file-containing-the-global-variable.js'
],
59
Michael Benford

La première solution n'a pas fonctionné pour moi dans Angular 2.1.x. Elle ne reconnaîtrait tout simplement pas la variable dans mon service importé. Ce que je devais faire était de mettre ma variable d'environnement dans mon karma-test-shim.js fichier et supprimez var afin qu'il soit disponible dans le monde entier.

Le mien ressemble à ceci:

Error.stackTraceLimit = Infinity;

require('core-js/es6');
require('reflect-metadata');

require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy'),
require('zone.js/dist/sync-test'),
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');

// Add environment variables here so that tests will inject them in source code
API_URL = 'http://localhost:8080/api/';

var appContext = require.context('../src', true, /\.spec\.ts/);

appContext.keys().forEach(appContext);

var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');

testing.TestBed.initTestEnvironment(
    browser.BrowserDynamicTestingModule,
    browser.platformBrowserDynamicTesting()
);
5
occasl

Si vous venez de Angular 2+ la seule façon dont j'ai trouvé que cela fonctionne est de créer la variable ou l'objet globalement en utilisant window:

Google Recapthca chargé à partir d'un script:

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>

Dans cet exemple, un appel à Google Recaptcha créera une variable globale appelée grecaptcha.

Dans notre composant, nous décidons de rendre un nouveau Google Recaptcha. Bien sûr, puisque nous ne déclarons pas grecaptcha, nous devons utiliser declare var pour dire bon je promets que c'est déclaré quelque part:

declare var grecaptcha;

private CreateGoogleCaptcha() {
  grecaptcha.render('recaptcha', {
    sitekey: this.siteKey,
    callback: this.GoogleCaptchaCallback,
    badge: 'inline'
  });
}

private GoogleCaptchaCallback(token) {
   // Handle Callback Logic
}

Maintenant que notre fonction fonctionne, nous décidons d'exécuter un test mais bien sûr, nous aimerions nous moquer de notre grecaptcha car nous n'avons aucun contrôle sur celui-ci. Nous nommons donc notre variable globale que nous aimerions créer et ajouter les fonctions que nous aimerions:

beforeEach(() => {
  fixture = TestBed.createComponent(GoogleRecaptchaComponent);
  component = fixture.componentInstance;

  window['grecaptcha'] = {
    render() {
      console.log('mocked global variable and function');
    }
  }
}

Mise à jour:

La création de la variable globale dans le beforeEach est très bien mais qu'en est-il quand il a une sorte de fonction de rappel telle que ci-dessus qui appelle une fonction de votre composant? Assez facile, nous déplaçons simplement la connexion à notre test et dans notre maquette, nous la définissons sur la fonction de nos composants:

it('should ', () => {
  window['grecaptcha'] = {
    render: function() { GoogleRecaptchaComponent['GoogleCaptchaCallback']('token'); }
  };

  spyOn<any>(GoogleRecaptchaComponent, 'GoogleCaptchaCallback');

  GoogleRecaptchaComponent['CreateGoogleCaptcha']();
  expect(GoogleRecaptchaComponent['GoogleCaptchaCallback']).toHaveBeenCalled();
});

Remarque:spyOn<any>: Le <any> est utilisé pour que nous puissions référencer sans erreur la fonction car elle est privée, sinon nous obtiendrons une erreur TypeScript;

5
L1ghtk3ira