Search code examples
angularcypress

How do you use NgModel in a Cypress Component Test on an Angular Component?


I have searched, but I cannot find an example of how to use ngModel in a Cypress Component Test, nor can I find an explanation of why this is not recommended. The component I am attempting to test does implement ControlValueAccessor and it seems like a good test case to ensure that it interacts properly with ngModel, however when I attempt to add ngModel to componentProperties I receive the error message:

Object literal may only specify known properties, and 'ngModel' does not exist in type...

I understand that this essentially means that ngModel is not a property of my component, however I do not see another way to add ngModel and supply a value. For context, the component I am attempting to test is a button bar component. It accepts an array of options and renders each option as a button. The ngModel value is the value of the selected option. I want to ensure that when I pass in an option to ngModel that the appropriate button becomes selected. Additionally, I want to ensure that when I click on one of the buttons, the appropriate value is emitted from ngModelChange.

Below is my simple example:

it('Interacts properly with ngModel', () => {
    cy.mount(ButtonBarComponent, {
        componentProperties: {
            options: ['Option 1', 'Option 2', 'Option 3'],
            ngModel: 'Option 1', // <-- Does not work
            ngModelChange: createOutputSpy("ngModelChangeSpy") // <-- Does not work
        }
    });
});

I would expect that I could pass values into ngModel and have the component UI updated to reflect this. Also, I would expect to be able to watch for changes caused by UI interaction via ngModelChange. Neither of these work.


Solution

  • I have found a way to accomplish interaction with ngModel via Angular Template Syntax.

    it('Interacts properly with ngModel', () => {
        cy.mount(
            '<button-bar [options]="options" [ngModel]="selection" (ngModelChange)="modelChange.emit($event)"></button-bar>', {
            imports: [FormsModule],
            declarations: [ButtonBarComponent],
            componentProperties: {
                options: ['Option 1', 'Option 2', 'Option 3'],
                selection: 'Option 1', 
                modelChange: createOutputSpy("ngModelChangeSpy") 
            }
        });
    });
    

    selection and modelChange are available in componentProperties because I am using them in the template. Note that I have also imported the Angular FormsModule. Otherwise, ngModel would not be available.

    I would still like to know if there is a way to accomplish this without using Angular Template Syntax. If someone can provide that answer then I will mark it as the accepted answer.