简体   繁体   中英

Cannot mock "window" with jasmine/karma and typescpript

I am trying to mock "window" object in the jasmine/karma unit tests. I've tried almost all solutions and anything didn't help me.

  1. The simpliest:
const mockWindow: any = () => {
            return {
                navigator: {
                    userAgent: "Edge"
                }
            };
        };

//in some test
window = mockWindow();

Error: TypeError: Attempted to assign to readonly property. (line25) "Jasmine"

  1. Another one:
class MockWindow {
        public navigator =  { userAgent: "Edge" };
    }

//in some test
window = new MockWindow() as any;

Error: TypeError: Attempted to assign to readonly property. (line25) "Jasmine"

  1. Using defineProperty:
Object.defineProperty(navigator, "userAgent", {
                value: () => "Edge",
                configurable: true,
                writable: true
            });

As you can see, I've also tried this solution with attributes like "configurable" and "writable".

Error: TypeError: Attempting to configurable attribute of unconfigurable property. (line 25) "Jasmine"

  1. Using jasmine mock:
spyOn<any>(window, "navigator").and.returnValue({ userAgent: "Edge" });

It runs without errors but window isn't mocked. 5. Tricky one:

window.navigator['__defineGetter__']('userAgent', function(){
    return 'Edge';
  });

Error: TS7053: Element implicitly has an 'any' type because expression of type '" defineGetter "' >can't be used to index type 'Navigator'.
Property ' defineGetter ' does not exist on type 'Navigator'.

I'm sure some solution must exist. I remember doing the same mock in another project and everything worked good. Maybe I have to add some configuration properties in the karma/jasmine/typescript configs.

Please help!)

The window object contains most of the environment, so nuking it would not be a great idea. I think that what you are actually trying to do is overwrite the browser userAgent string.

If you run:

Object.getOwnPropertyDescriptor(window.navigator, 'userAgent');
// {"writable":false,"enumerable":false,"configurable":false}

You see that the property is not configurable or writable. This is why it fails to overwrite it.

However, you can try:

navigator.__defineGetter__('userAgent', function () { return 'Edge'; });

Use it with caution, as it is deprecated. Object.prototype. defineGetter ()

As of February 2020 you can change the reported userAgent string in Chrome DevTools .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM