79 votes

simuler window.location.href en Javascript

J'ai quelques tests unitaires pour une fonction qui utilise window.location.href -- ce n'est pas l'idéal, j'aurais préféré passer cette valeur mais ce n'est pas possible dans l'implémentation. Je me demande simplement s'il est possible de simuler cette valeur sans que la page de mon programme de test aille réellement vers l'URL.

  window.location.href = "http://www.website.com?varName=foo";    
  expect(actions.paramToVar(test_Data)).toEqual("bar"); 

J'utilise jasmine pour mon cadre de test unitaire.

1 votes

J'ai le même problème lorsque je veux appeler une fonction à l'intérieur de l'objet with. Comment le résoudre ?

2voto

Jake Dugas Points 31

Cette solution est similaire à la suggestion de cpimhoff, mais elle utilise plutôt l'injection de dépendances dans Angular. Je me suis dit que j'allais l'ajouter au cas où quelqu'un d'autre viendrait ici à la recherche d'une solution Angular.

Dans le module, probablement le app.module ajouter un fournisseur de fenêtre comme ceci :

@NgModule({
...
  providers: [
    {
      provide: Window,
      useValue: window,
    },
  ],
...
})   

Ensuite, dans votre composant qui fait usage de window, injectez window dans le constructeur.

constructor(private window: Window)

Maintenant, au lieu d'utiliser directement la fenêtre, utilisez la propriété component lorsque vous utilisez la fenêtre.

this.window.location.href = url

Avec cela en place, vous pouvez définir le fournisseur dans les tests Jasmine en utilisant TestBed.

    beforeEach(async () => {
      await TestBed.configureTestingModule({
        providers: [
          {
            provide: Window,
            useValue: {location: {href: ''}},
          },
        ],
      }).compileComponents();
    });

1voto

AngularBoy Points 1121

Cela fonctionne pour moi :

delete window.location;
window.location = Object.create(window);
window.location.href = 'my-url';

0voto

Tongfa Points 1152

Selon moi, cette solution est une petite amélioration de celle de cburgmer, car elle permet de remplacer window.location.href par $window.location.href dans la source. Il est vrai que j'utilise Karma et non Jasmine, mais je pense que cette approche peut fonctionner avec l'un ou l'autre. Et j'ai ajouté une dépendance sur sinon.

D'abord un service / singleton :

function setHref(theHref) {
    window.location.href = theHref;
}
function getHref(theHref) {
    return window.location.href;
}

var $$window = {
        location: {
            setHref: setHref,
            getHref: getHref,
            get href() {
                return this.getHref();
            },
            set href(v) {
                this.setHref(v);
            }
        }
    };
function windowInjectable() {  return $$window; }

Maintenant, je peux définir l'emplacement.href dans le code en injectant windowInjectable() comme $window comme ceci :

function($window) {
  $window.location.href = "http://www.website.com?varName=foo";
}

et le mettre dans un test unitaire, ça ressemble à ça :

sinon.stub($window.location, 'setHref');  // this prevents the true window.location.href from being hit.
expect($window.location.setHref.args[0][0]).to.contain('varName=foo');
$window.location.setHref.restore();

La syntaxe getter / setter remonte à IE 9, et est par ailleurs largement supportée selon https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set

0voto

cpimhoff Points 560

Voici ma solution générique qui nécessite une importation supplémentaire dans le code de production, mais qui ne requiert pas d'injection de dépendances ou d'écriture de fonctions wrapper individuelles telles que getHref() .

En gros, nous jetons la fenêtre dans un fichier séparé, puis notre code de production importe la fenêtre indirectement depuis ce fichier.

En cours de production, windowProxy === window . Dans les tests nous pouvons muter le module qui exporte windowProxy et le remplacer par une nouvelle valeur temporaire.

// windowProxy.js

/*
 * This file exists solely as proxied reference to the window object
 * so you can mock the window object during unit tests.
 */
export default window;

// prod/someCode.js
import windowProxy from 'path/to/windowProxy.js';

export function changeUrl() {
  windowProxy.location.href = 'https://coolsite.com';
}

// tests/someCode.spec.js
import { changeUrl } from '../prod/someCode.js';
import * as windowProxy from '../prod/path/to/windowProxy.js';

describe('changeUrl', () => {
  let mockWindow;
  beforeEach(() => {
    mockWindow = {};
    windowProxy.default = myMockWindow;
  });

  afterEach(() => {
    windowProxy.default = window;
  });

  it('changes the url', () => {
    changeUrl();
    expect(mockWindow.location.href).toEqual('https://coolsite.com');
  });
});

-1voto

Youssef Gamil Points 256

Tu dois faire semblant window.location.href tout en étant sur la même page. Dans mon cas, ce bout de phrase a parfaitement fonctionné :

$window.history.push(null, null, 'http://server/#/YOUR_ROUTE');
$location.$$absUrl = $window.location.href;
$location.replace();

// now, $location.path() will return YOUR_ROUTE even if there's no such route

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X