I'm writing a test for a dialog component, that handles the PWA install event prompted manually when a function is called. It will then resolve the promise coming back from the BeforeInstallPromptEvent.userChoice
property.
However when I try to test this function I get an error from jasmine:
'userChoice.then is not a function'
Which I understand since I tried spying on that with a spyOn to then check the result.
I tried a few other things with Promises, since the userChoice returns a resolved promise (https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent) but nothing has worked so far.
This is the function I am trying to test. The BeforeInstallPromptEvent
is stored in the installEvent object that gets passed down to the component from the app.ts
and then stored in data.
this.data.installEvent.userChoice
.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
doSomething();
In my test spec I created a mockData object with the following:
const mockData = {
installEvent: {
prompt: () => {},
userChoice: Promise.resolve().then(() => {
return { choiceResult: { outcome: "accepted" } };
}),
},
};
My test spec so far (after many different tries) is either this:
it("should do something after user accepted", fakeAsync(() => {
mockData.installEvent.userChoice.then((result) => {
return result.choiceResult.outcome;
//this test returns true
expect(result.choiceResult.outcome).toEqual("accepted");
});
flush();
//but the function gets never called
expect(component.doSomething).toHaveBeenCalled();
});
Or with the spyOn
function on the userChoice
that produces the error:
it("should do something after user accepted", () => {
spyOn(mockData.installEvent, "userChoice").and.returnValue("accepted");
expect(mockData.installEvent.userChoice).toBe("accepted)
expect(component.doSomething).toHaveBeenCalled();
});
With that I managed to already test that the data.installEvent.prompt
function is getting called.
But I don't know how to test that the userChoice
Promise resolves to "accepted" and then triggers the if condition.
Please help me. Since I am a beginner regarding testing (in Angular) it would be nice to get an explanation of the method behind testing such Promises.
Thank you very much in advance!
The issue is you're resolving the promise already in mockData
and the spy is not returning a promise.
Method 1
const mockData = {
installEvent: {
prompt: () => {},
userChoice: Promise.resolve({ choiceResult: { outcome: "accepted" } }),
},
};
it("should do something after user accepted", fakeAsync(() => {
mockData.installEvent.userChoice.then((result) => {
// return result.choiceResult.outcome;, remove return here and only test the assertion
//this test returns true
expect(result.choiceResult.outcome).toEqual("accepted");
expect(component.doSomething).toHaveBeenCalled(); // make sure doSomething gets called
});
flush(); // flush the promises
});
Method 2 (can't be done)
it("should do something after user accepted", () => {
// you can't spy on userChoice since you can only spy on methods/functions and not variables
spyOn(mockData.installEvent, "userChoice").and.returnValue("accepted");
expect(mockData.installEvent.userChoice).toBe("accepted)
expect(component.doSomething).toHaveBeenCalled();
});
Method 2 can't be done because you can only spyOn
methods and functions and not properties.