I'm having trouble doing a negative test of an ngIf statement that looks at a property on my authService.
I have a mock provider already, and the positive version of this test works great. I can see that the HTML is pulling the data from my mock and correctly reflecting it in the DOM. If I change a value in the mock, I can fail the test.
What I haven't been able to do is to write a test to set the userData object from the mock to 'null' so that the ngIf fails and I can confirm the selector is undefined. If I change the actual mock for userData to (null) that works, but I'm not quite understanding how to spy on the mock and return a different value in a test.
HTML to Be Tested
<div class="fs-4 text-secondary" *ngIf="authService.userData as user">
<p id="confirmText">We have sent a confirmation email to <strong>{{user.email}}</strong>.</p>
<p>Please check your email and click on the link to verfiy your email address.</p>
</div>
AuthServiceMock
import { User } from "../shared/interface/user";
const authState: User = {
uid: 'fakeuser',
email: '[email protected]',
emailVerified: true
};
export const AuthServiceMock = {
ForgotPassword: () => {
return
},
SignUp: () => {
return
},
userData: (authState)
};
Basic Test That Passes
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [VerifyEmailAddressComponent],
providers: [{ provide: AuthService, useValue: AuthServiceMock }]
})
.compileComponents();
fixture = TestBed.createComponent(VerifyEmailAddressComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('Text Rendered - Logged In', () => {
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('#confirmText')?.textContent).toContain('We have sent a confirmation email to [email protected].');
});
Because I'm going just going after a property (userData) in the mock, and not a method spyOn() gives me errors, so I assumed I should use 'spyOnProperty', but I can't even get that to return let alone a null value:
SpyOnProperty Attempt, I just wanted to see if I could manipulate the return values
it('Text Rendered - Not Logged In', () => {
const compiled = fixture.nativeElement as HTMLElement;
spyOnProperty(AuthServiceMock, 'userData', 'get').and.returnValue({
uid: '1234',
email: '[email protected]',
emailVerified: false
})
//expect(compiled.querySelector('#confirmText')?.textContent).toBeUndefined();
console.log(AuthServiceMock.userData)
});
Running this produces the following error:
Error: : Property userData does not have access type get
I've tried a couple of other things, but I haven't been able to find a solution to this one yet. Any help in how i can return null for the userData object from my mock would be most appreciated.
You can directly create a get property for mocking it
const AuthServiceMock = {
ForgotPassword: () => {
return
},
SignUp: () => {
return
},
_authState: authState,
get userData() {
return this._authState;
},
set userData(value: any) {
this._authState = value;
}
};
I think you need to spy on the instance
of a class and not on the actual class, you can try either.
it('Text Rendered - Not Logged In', () => {
const compiled = fixture.nativeElement as HTMLElement;
const component = fixture.componentInstance;
spyOnProperty(component.authService, 'userData', 'get').and.returnValue({
uid: '1234',
email: '[email protected]',
emailVerified: false
})
console.log(omponent.authService.userData)
});
Or you can try.
it('Text Rendered - Not Logged In', () => {
const compiled = fixture.nativeElement as HTMLElement;
const authService = TestBed.inject(AuthService);
spyOnProperty(authService, 'userData', 'get').and.returnValue({
uid: '1234',
email: '[email protected]',
emailVerified: false
})
console.log(authService.userData)
});