In our Angular porject, We are migrating jasmine tests to jest. We are getting some issues when we try to mock @Input values of components in the tests. For example, in jamsine we use to write something like this :
@Component({
selector: 'app-message[message]',
templateUrl: './message.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MessageComponent implements OnInit {
@Input() message!: Message;
}
describe('MessageComponent', () => {
let component: MessageComponent ;
let fixture: ComponentFixture<MessageComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [// some imports],
declarations: [MessageComponent]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MessageComponent);
component = fixture.componentInstance;
});
it('test1 with input message') {
component.message = new Message('xxx');
fixture.detectChanges();
// some expectations
}
it('test2 with another input message') {
component.message = new Message('yyy');
fixture.detectChanges();
// some expectations
}
});
With jasmine, these tests were always passing and the instance of Message was always set like this in the tests. But with jest, everytime fixture.detectChanges() is called, the component is reset and all the @Input values are set to undefined and I do not know how to deal with it. I then try another way for doing it insprired by (Angular Unit-Test) How to mock input property in Jasmin? and I now use a HostComponent to call my template like
let testMessage: Message = generateMessage();
@Component({
selector: 'app-testhost',
template: `<app-message [message]="message"></app-message>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FakeHostComponent {
message = testMessage;
}
It works fine if I have only 1 test but I do not know how I can change the value of "message" dynamically in each tests. I feel like I'm missing something or doing something wrong. Should I create a FakeHostComponent for each of my tests ?
So I need help to make these tests a bit prettier and more dynamics. Also I would like to understand why fixture.detectChanges() reset my component input values
As a workaround, I put the value of message in a global variable "testMessage" and create this method that I call in every test, but I am sure there is a way to do it more properly
const createComponent = (message: Message) => {
testMessage = message;
fixture = TestBed.createComponent(FakeHostComponent);
component = fixture.debugElement.children[0].componentInstance;
};