# Test with Jest and calling public method on component

**URL:** <https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941>\
**Category:** Help Requests\
**Created:** [October 9, 2022, 10:19pm UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941 "2022-10-09T22:19:16Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![magnusdanielson](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/magnusdanielson/32/924_2.png) [@magnusdanielson](https://discourse.aurelia.io/u/magnusdanielson)\
**Post date:** [October 9, 2022, 10:19pm UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/1 "2022-10-09T22:19:16Z")

</div>

I have a component that works as expected. I have also a working set up with Aurelia and Jest. I have also created some tests with something similar to below:

```auto
component = StageComponent
    model = {
      "strongMessage":"Yo"
    };
    .withResources('elements/message-bar')
    .inView('<message-bar strong-message.one-time="strongMessage"></message-bar>')
    .boundTo(model);

component.bootstrap((aurelia: Aurelia) => {
      return aurelia.use
        .standardConfiguration();
    });
    
    await component.create(bootstrap);
    const view:Element = component.element;
      expect(view.querySelector(".someclass").textContent.trim()).toBe('Yo');

```

Above works fine and as expected. In above example all changes to the UI is dependent on the model.

But if I call a public method that changes the values of the viewmodel

```auto
const messageBar = Container.instance.get(MessageBar) as MessageBar;
messageBar.DoStuff();

```

It is not reflected in the UI. The method updates a property (strongMessage) that are used in the view.

`<span class="ms-fontWeight-semibold">${strongMessage}</span>`

Is there anything I need to do to make it rerender when under test. It works just fine in the real app.

The point of the test is to make sure that the view presents the strong messsage and that the method show actually sets the property correctly. So it does not feel correct just to test the strongmessage value on the viewmodel.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [October 10, 2022, 4:10am UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/2 "2022-10-10T04:10:09Z")

</div>

Custom elements and attributes do not register their view model instances with the root container. When you do `Container.instance.get(MessageBar)`, you are actually creating a new instance of that component.

What can be done is to get the element and then get the view model based on the controller instead

```nohighlight
host.querySelector('message-bar').$au.controller
  .viewModel
  .DoStuff();

```

In v2, we have an official API for retrieving the controller of a custom element. The equivalent of it in v2 is

```nohighlight
CustomElement.for(host.querySelector('message-bar'))
  .viewModel
  .DoStuff();

```

---

<div class="post-metadata">

**Author:** ![magnusdanielson](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/magnusdanielson/32/924_2.png) [@magnusdanielson](https://discourse.aurelia.io/u/magnusdanielson)\
**Post date:** [October 10, 2022, 4:53pm UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/3 "2022-10-10T16:53:36Z")

</div>

Thank you @bigopon for your great feedback.

That did not really solve the issue for me but got me in the correct direction. I was testing some properties for equality and have found this (which probably everybody already knows)

```auto
    // below lines are all true
    // component.host.querySelector('message-bar') == component.element
    // component.element.au.controller == component.element.au['message-bar']
    // component.rootView.firstChild == component.host 
    // component.viewModel == component.element.au.controller.viewModel

```

So to me it looks like the easiest way to get to the view and the view-model is:

```auto
component.element
component.viewModel

```

And then updating with

```auto
component.viewModel.DoStuff();

```

This fails (as before)

```auto
expect(component.element.querySelector(".someclass").textContent.trim()).toBe('Yo');

```

This fails too

```auto
const queue = component.rootView.container.get(TaskQueue) as TaskQueue;
    queue.queueTask(() => {
      expect(component.element.querySelector(".someclass").textContent.trim()).toBe('Yo');
    });
queue.flushTaskQueue();

```

But this works fine

```auto
setTimeout(()=>{
      expect(component.element.querySelector(".someclass").textContent.trim()).toBe('Yo');
    },0);

```

To me it looks like I need to wait for the setTimeout()

This test is fine by me and I will keep it like this unless anyone has a strong argument against it.

Happy coding 🙂

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [October 12, 2022, 10:34am UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/4 "2022-10-12T10:34:07Z")

</div>

Yes, the behavior you observed is because the component tester automatically retrieve the first view model controller (either custom element/attribute) to return it with `component.viewModel`. What you have works fine and simpler for single element/attribute test case. If you ever have more than one, then doing it the query + `$au` way will give easier time.  
Regardless, happy coding 🙂

---

<div class="post-metadata">

**Author:** ![magnusdanielson](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/magnusdanielson/32/924_2.png) [@magnusdanielson](https://discourse.aurelia.io/u/magnusdanielson)\
**Post date:** [October 12, 2022, 8:16pm UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/5 "2022-10-12T20:16:29Z")

</div>

Excellent! Does it make sense to you that I hade to use

```auto
setTimeout( ()=> expect(),0);

```

to get the updated value from the view?

---

<div class="post-metadata">

**Author:** ![magnusdanielson](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/magnusdanielson/32/924_2.png) [@magnusdanielson](https://discourse.aurelia.io/u/magnusdanielson)\
**Post date:** [October 18, 2022, 10:11am UTC](https://discourse.aurelia.io/t/test-with-jest-and-calling-public-method-on-component/4941/6 "2022-10-18T10:11:49Z")

</div>

If anyone ends up here this is what I did in the end in the test method:

```auto
 it('says "abc"',async () => {
    var element1:Element = component.element; 
    var vm1:MessageBar = component.viewModel;       
    
   // make the call to the viewModel
    vm1.show("abc","abc","info");
    await TestHelper.waitForUI();
    expect(element1.querySelector(".ms-fontWeight-semibold").textContent.trim()).toBe('abc');
  });

```

And the we have the TestHelper:

```auto
export class TestHelper
{
    static waitForUI()
    {
        return new Promise(function(resolve, reject) {
            setTimeout(resolve, 0);
        });
    }
}

```
