Vuetify, data-app="true" and problems rendering <v-dialog> in unit tests

In unit tests, I get the following warnings:

console.warn node_modules/vuetify/dist/vuetify.js:470
[Vuetify] Unable to locate target [data-app] in "v-menu"

console.warn node_modules/vuetify/dist/vuetify.js:470
[Vuetify] Unable to locate target [data-app] in "v-dialog"

If, before mounting the component, I do:

const app = document.createElement('div');
app.setAttribute('data-app', true);
document.body.append(app);

Then the error goes away.

At this point, all looks good, Vue and Vuetify components get rendered just fine, with the exception of <v-dialog>; its definition is:

<v-dialog class="sysmsg js-sysmsg" max-width="500px">
  <v-card>
    <v-card-title>
      <span class="headline">Important Information</span>
    </v-card-title>
    <v-card-text>
      Please note that you must use the force.
    </v-card-text>
    <v-card-actions>
      <v-btn color="primary" flat >Close</v-btn>
    </v-card-actions>
  </v-card>
</v-dialog>

As you see, there is no use of dynamic data, just plain text. Still, it gets rendered as:

<div class="dialog__container sysmsg js-sysmsg" style="display: block;"></div>

Strangely, if I remove that <div data-app="true"> that I append to the body before mounting the component, I get the warnings but then <v-dialog> get’s rendered just fine, with all its inner content.

Any ideas of what could be going on here?

I have the same issue.
My workaround is to wrap the component into another component with a data-app attribute.

  let myComponent

  beforeEach(() => {
    const localVue = createLocalVue()
    localVue.use(Vuetify)
    // create a local <App> container with a [data-app] attribute
    // to prevent v-tooltip "Unable to locate target" warning
    const App = localVue.component('App', {
      components: { MyComponent },
      template: `
        <div data-app>
          <MyComponent />
        </div>
      `
    })

    const mountedApp = mount(App, {
      localVue,
      attachToDocument: true
    })
    myComponent = mountedApp.find(MyComponent)
  })

1 Like

I have found a different approach that doesn’t require mounting the component to be tested inside another component, and then finding it.

/**
 * Adds a warapping `div data-app="true"` to the body so that we don't
 * get Vuetify complaining about missing data-app attribute for some components.
 *
 * @return undefined
 */
function addElemWithDataAppToBody() {
  const app = document.createElement('div');
  app.setAttribute('data-app', true);
  document.body.append(app);
};

Then, at the top of test files that produce the warning about the missing data-app attribute, just invoke the function:

// Foo.spec.js
addElemWithDataAppToBody();

beforeEach(() => {
  describe('Foo.spec.js', () => {
    it('should work', () => {
      expect(true).toBe(true);
    });
  });
});

Not sure what are the pros and cons of each of these two solutions, though. What I can say that your workaround looks more professional.

Thanks a lot for helping me out.

3 Likes

However, it returns an empty wrapper

    [vue-test-utils]: find did not return Component, cannot call setProps() on empty Wrapper

      45 |
      46 |     // Act
    > 47 |     expect(mountedApp.exists()).toBe(true)

No es necesario código JS adicional para esto, todos las elementos de vuetify deben estar dentro de las etiquetas "<v-app>...</v-app>":

<div id="app" >
    <v-app>
          ....  All your components, routers, views  here ...
    </v-app>
</div>

O en su defecto:

<div id="app" app-data="true">
          ....  All your components, routers, views  here ...
</div>
6 Likes

This one worked like a charm! Thanks.

You can use the option attachToDocument of mounting, like :

shallowMount(yourComponent, {
    attachToDocument: true,
}) 

Documentation Here

2 Likes

I hate to resurrect this thread, but I am having the exact same problem. I’ve tried the original author’s solution and the accepted answer. Neither work for me.

Does anyone have a working solution for this?

Try with document.body.setAttribute('data-app', true).

const localVue = createLocalVue()
localVue.use(Vuetify)
document.body.setAttribute('data-app', true)
mount(YourComponent, { localVue })
12 Likes

This works for me: Vuetify, data-app="true" and problems rendering <v-dialog> in unit tests

I tried everything and at the end added data-app=“true” to a body selector and voila.

Thank you!

Thanks, roparz, it works for me!

Any solution or doesn’t work or brokes snapshot test. Do anybody have correct solution?

The ‘correct’ approach is to use parentComponent and VApp.

By correct, I mean we do not have to reproduce the side-effects of v-app (i.e. its data-app attribute) which are internal to Vuetify.



wrapper = mount(ComponentUnderTest, {
  localVue,
  vuetify,
  parentComponent: {
    render: (createElement) => createElement(VApp)
  }
})

This creates a very efficient component that renders a v-app and the wrapper uses it to mount ComponentUnderTest under.

Edit: for the life of me, I can’t get it to work. Falling back to:

wrapper.element.ownerDocument.body.setAttribute('data-app', true)