J'essaie d'écrire des tests pour mes projets de composants Web en plaisantant. J'utilise déjà babel avec es2015 preset. Je suis confronté à un problème lors du chargement du fichier js. J'ai suivi un morceau de code où l'objet document
a un objet currentScript
. Mais dans le contexte du test, il est null
. Alors je pensais me moquer de la même chose. Mais jest.fn()
ne vous aide pas vraiment. Comment puis-je gérer ce problème?
Morceau de code où la plaisanterie échoue.
var currentScriptElement = document._currentScript || document.currentScript;
var importDoc = currentScriptElement.ownerDocument;
Cas de test que j'ai écrit. component.test.js
import * as Component from './sample-component.js';
describe('component test', function() {
it('check instance', function() {
console.log(Component);
expect(Component).toBeDefined();
});
});
Voici l'erreur lancée par la plaisanterie
Test suite failed to run
TypeError: Cannot read property 'ownerDocument' of null
at src/components/sample-component/sample-component.js:4:39
Mise à jour: Comme suggéré par Andreas Köberle, j’ai ajouté quelques vars globaux et essayé de me moquer comme suit
__DEV__.document.currentScript = document._currentScript = {
ownerDocument: ''
};
__DEV__.window = {
document: __DEV__.document
}
__DEV__.document.registerElement = jest.fn();
import * as Component from './arc-sample-component.js';
describe('component test', function() {
it('check instance', function() {
console.log(Component);
expect(Component).toBeDefined();
});
});
Mais pas de chance
Mise à jour: J'ai essayé le code ci-dessus sans __dev__
. Également en définissant le document comme global.
J'ai résolu ceci en utilisant la propriété setUpFiles
en plaisanterie. Cela fonctionnera après jsdom et avant chaque test, ce qui est parfait pour moi.
Définissez setupFiles, dans Jest config, par exemple:
"setupFiles": ["<rootDir>/browserMock.js"]
// browserMock.js
Object.defineProperty(document, 'currentScript', {
value: document.createElement('script'),
});
La situation idéale serait de charger webcomponents.js pour polyfill le jsdom.
Semblable à ce que d'autres ont dit, mais au lieu d'essayer de vous moquer du DOM vous-même, utilisez simplement JSDOM:
__mocks __/client.js
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
Puis dans votre config de plaisanterie:
"setupFiles": [
"./__mocks__/client.js"
],
Je pouvais résoudre ce même problème en utilisant le module global
scope sur nodejs, en mettant un document avec un modèle de document, dans mon cas, getElementsByClassName
:
// My simple mock file
export default {
getElementsByClassName: () => {
return [{
className: 'welcome'
}]
}
};
// Your test file
import document from './name.component.mock.js';
global.document = {
getElementsByClassName: document.getElementsByClassName
};
Si, comme moi, vous cherchez à transformer un document en document non défini (par exemple, pour les tests côté serveur/côté client), j'ai été en mesure d'utiliser object.defineProperty dans mes suites de tests sans devoir utiliser setupFiles
Exemple:
beforeAll(() => {
Object.defineProperty(global, 'document', {});
})
Si vous devez définir des valeurs de test pour les propriétés, il existe une approche légèrement plus granulaire. Chaque propriété doit être définie individuellement et il est également nécessaire de rendre les propriétés writeable
:
Object.defineProperty(window.document, 'URL', {
writable: true,
value: 'someurl'
});
Voir: https://github.com/facebook/jest/issues/890
Cela a fonctionné pour moi en utilisant Jest 21.2.1
et Node v8.11.1
Je me suis battu avec le document moqueur pour un projet sur lequel je suis. J'appelle document.querySelector()
dans un composant React et je dois m'assurer qu'il fonctionne correctement. En fin de compte, c’est ce qui a fonctionné pour moi:
it('should test something', () => {
const spyFunc = jest.fn();
Object.defineProperty(global.document, 'querySelector', { value: spyFunc });
<run some test>
expect(spyFunc).toHaveBeenCalled()
});