Is there a way to get this Jest test including document.fonts.ready
to pass, e.g. by adding/removing any amount of setup/installing dependencies, without triggering or silencing any TypeScript errors/warnings?
describe('Input', () => {
beforeAll(() => {
// Core part of the workaround...it seems the global prefix can also optionally be added
global.document.fonts = {
ready: {
then: jest.fn()
}
};
});
test('should render an Input', () => {
expect(renderInput()).toMatchSnapshot();
});
});
Context: I had a production reason to use document.fonts.ready
, for example as per this SO.
In flow (for legacy reasons, could rewrite in TypeScript if it helps) and React classes, this can be coded as something like:
export default class Input extends React.Component<any, any> {
constructor(props: any) {
super(props);
(document: any).fonts.ready.then(() => this.setState({
value: props.defaultValue || ''
}));
}
...
However when the test is brought into TypeScript contexts, for example by a component including (and not mocking) that Input
component, it triggers TS2339: Property 'fonts' does not exist on type 'Document'.
out of the box.
This is generally silenced by a // @ts-ignore TS2339
, which is probably enough for most people. However, sometimes we're curious :D
Attempt 1: A yarn add -D @types/css-font-loading-module
(thanks to all contributing here!) merely triggers a different later warning:
TS2739: Type '{ then: Mock<any, any>; }' is missing the following properties
from type 'Promise<FontFaceSet>': catch, [Symbol.toStringTag], finally
Unfortunately that seemed to lead down a rabbit hole of more errors...
Attempt 2: I was inspired by this post on mocking global.window
with jest to try something that at least looked plausible (when combined with Attempt 1 above):
jest.spyOn(global.document.fonts, 'ready', 'get')
However that causes the test to fail to run Cannot spyOn on a primitive value; undefined given
.
Exploring jsdom, e.g. here suggests document.fonts
is not yet implemented. So I am stumped for now.