Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest mock documentElement lang property

I'm trying to manipulate documentElement lang property for my tests. And can't figure it out how can I accomplished that. I've already tried defining setupFiles in Jest config - and that gave me possibility to define it and no option to change it for different tests - as described here: Mocking `document` in jest

Part of testing code looks like:

const lang: string = document.documentElement.lang ?
      document.documentElement.lang : Constraints.DEFAULT_LANGUAGE;

The test look like this:

   test('should pass `en` language when document hasn`t any specified', () => {
    const spy = jest.spyOn(window.document, 'documentElement', 'get');
    expect(spy).toHaveBeenCalled();
  });

And with setupFiles:

Object.defineProperty(document, 'documentElement', {
    writable: true,
    configurable: true,
    value: document.createElement('document')
});

When I have setupFiles I get error: Property documentElement does not have access type get

But when I try to spy on it without setupfile.js configured, spy is never called.

EDIT

More clear example what I'm trying to achieve:

    const lang: string = document.documentElement.lang ?
      document.documentElement.lang : Constraints.DEFAULT_LANGUAGE;
    component.src = `/${lang}/mysite`;
test('should pass `de` language when document has one specified', () => {
    const spy = jest.spyOn(window.document, 'documentElement', 'get');
    const mockElement = document.createElement('document');
    mockElement.lang = 'de';
    spy.mockReturnValue(mockElement);
    expect(component.src).toContain('/de/');
  });

And in test I'm getting:

expect(received).toContain(expected) // indexOf

    Expected substring: "/de/"
    Received string:    "http://localhost/en/mysite"

like image 643
Andreew4x4 Avatar asked Jun 26 '19 08:06

Andreew4x4


1 Answers

Well you are almost there, but when you access document.documentElement.lang property, the get accessor has been triggered. So you should define that object like below;

Object.defineProperty(document, 'documentElement', {
    configurable: true,
    get () {
        return document.createElement('document');
    },
});

And in your test;

before expect line you should add this line to trigger getter and make spy to be called.

window.document.documentElement.lang;

EDIT

Forget about above.

Simply remove your setup code block, you don't need a spy or something in my opinion.

Create a method for setting language into your constant. Then test that method instead of testing get action of documentElement.

Use the code for setting lang property below before calling your method. (Imagine you have language method)

test('should return `de` language when document has one specified', () => {
    Object.defineProperty(document.documentElement, 'lang', { value: 'de', configurable: true });

    expect(component.language()).toBe('de');
});
like image 148
Tugay İlik Avatar answered Oct 15 '22 09:10

Tugay İlik