Anyone know how to override properties and functions in a read only objects like window or [htmlelement].style?
Example function to need to test:
public static getCSSTransitionEvent(element: HTMLElement): string {
let transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (let transition in transitions) {
if (element.style[transition] !== undefined ) {
return transitions[transition];
}
}
return;
}
How can I override the transition property in element.style to tests that the function returns undefined at the bottom?
Another example, how do I test this if statement
function isCryptoAvailable() {
if (typeof (window.crypto) !== 'undefined' && typeof (window.crypto.getRandomValues) !== 'undefined') {
return true
}
else {
return false
}
}
This is done with property descriptors. Read-only properties have writable descriptor property set to false. As long as they are configurable, they can be redefined with Object.defineProperty like:
const cryptoDescriptor = Object.getOwnPropertyDescriptor(window, 'crypto');
afterEach(() => {
if (origCryptoDescriptor) {
delete window.crypto;
Object.defineProperty(window, 'crypto', cryptoDescriptor);
}
});
it('...', () => {
expect(origCryptoDescriptor).toBeTruthy();
expect(origCryptoDescriptor.configurable).toBeTruthy();
const cryptoMock = ...;
delete window.crypto;
window.crypto = cryptoMock;
...
});
The descriptor should be restored in afterEach because it will be executed even if test fails. And test will fail if a property is non-configurable. This is possible in some browsers, so a test should be excluded from suite in browsers that are known to fail it.
The same concerns a function that involves non-globals like HTMLElement object, but if it is possible to mock this object entirely instead of mocking its properties, this is the preferable strategy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With