Posted 2/20/2023
Using the secure context WebCrypto at window.crypto.subtle
offers a lot of powerful and fast cryptography functions directly in your browser. How about some asymmetric encrypting por favor? ¡Si, no problemo!
But how about testing the methods before using the in production? Sure, with Jest… Not so fast!
Using window.crypto.encrypt(algorithm, key, data)
you’ll notice that data
is a BufferSource
— but my data is a string so the TextEncoder
comes in handy turning a string to an array with new TextEncoder().encode(data)
. But look, what’s that?
ReferenceError: TextEncoder is not defined
Using the interwebs got me to this StackOverflow post, it turns out “jsdom” — the feature set used by Jest — does not include TextEncoder
and TextDecoder
. Say what? After a few minutes of looking around for a bit, it’s still unclear to me why. Let’s focus on fixing it. The clean solution that worked for me:
I created a little shim file, called it jest-shim.js
, and put it in my tests
folder. It’s loading the two missing classes from Node’s util
lib and exposes them on global
so that they are available while running the tests in the Jest environment.
import { TextDecoder, TextEncoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
Next, I edited jest.config.js
to tell it about that file by adding one extra line:
setupFiles: ['<rootDir>/tests/jest-shim.js'],
But look at this, the next one!
TypeError: Cannot read properties of undefined (reading 'subtle')
Looking around online didn’t bring up much, but again this StackOverflow post gave me an idea: for whatever reason, the WebCrypto
object is also not available as it would be in the browser. But now we know what to do… So back to the shim
file, Robin! Let’s add a few lines:
import { TextDecoder, TextEncoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
Object.defineProperty(globalThis, 'crypto', {
value: require('crypto').webcrypto,
});
With these, the encoders and decoders as well as crypto
object are in place. Hope it helps for more people to start using WebCrypto. It has so much potential when it comes to creating web3 apps that rely on shared or local storage and want to share data in a secure way. If you want to learn more about WebCrypto, MDN is a good place to get started.