Vue-test-utils: Get deprecated notification while using findAll() on html/css selector (no Vue component)

Created on 1 Oct 2020  路  5Comments  路  Source: vuejs/vue-test-utils

Subject of the issue

It is not possible to run findAll() without getting the deprecation notice:

finding components with `findAll` is deprecated and will be removed in the next major version. Use `findAllComponents` instead.

But it is not possible to use findAllComponents() if the wrapper is a non-vue component.

You will receive the following error:

Error: [vue-test-utils]: You cannot chain findAllComponents off a DOM element. It can only be used on Vue Components.
    at throwError (dist/js/webpack:/node_modules/@vue/test-utils/dist/vue-test-utils.js:1700:1)
    at Wrapper.findAllComponents (dist/js/webpack:/node_modules/@vue/test-utils/dist/vue-test-utils.js:10529:1)
    at Context.<anonymous> (dist/js/webpack:/tests/unit/tenant/tests/migration-job-list.spec.js:87:1)
    at processImmediate (internal/timers.js:456:21)

Steps to reproduce

notice: I'm using mocha and chai-should

import {createLocalVue, shallowMount} from '@vue/test-utils';

let localVue;
localVue = createLocalVue();

it("test rows of table", () => {
  wrapper = shallowMount(MyComponent, {
      localVue
  });

  const table = cardBody.find("table");
  table.exists().should.equal(true);

  const rows = table.findAllComponents(TableRow);
  rows.length.should.equal(3);
});

Expected behaviour

const rows = table.findAllComponents(TableRow) should return a WrapperArray containing all TableRow components.

OR

const rows = table.findAll(TableRow) should return a WrapperArray containing all TableRow components without display a deprecation notice.

Actual behaviour

receiving an error:

Error: [vue-test-utils]: You cannot chain findAllComponents off a DOM element. It can only be used on Vue Components.
    at throwError (dist/js/webpack:/node_modules/@vue/test-utils/dist/vue-test-utils.js:1700:1)
    at Wrapper.findAllComponents (dist/js/webpack:/node_modules/@vue/test-utils/dist/vue-test-utils.js:10529:1)
    at Context.<anonymous> (dist/js/webpack:/tests/unit/tenant/tests/migration-job-list.spec.js:87:1)
    at processImmediate (internal/timers.js:456:21)

Possible Solution

Don't show deprecation notice if you're using findAll() on non-vue component.

Most helpful comment

@lmiller1990 will be happy to try :+1:

All 5 comments

You cannot chain findComponent on a DOM node, since findComponent works with the virtual DOM (vdom) but find on the real DOM (two separate concepts). This is intentional.

Why not just do const rows = wrapper.findAllComponents(TableRow)? Or wrapper.findAll('tr')?

@lmiller1990 Since our components are rendering VNodes, I do not feel like these are two are separate concepts.
Especially there is no difference when we shallowMount - this usually means we intentionally want to stay within VNode concepts

Let me explain my point via real world example - sometimes we want in GitLab to use DOM element VNode as root of our search. Something like "Find gl-widget component in panel with specific title", where we are looking for panel (which is just <div>) having specific attribute and after that looking for specific widget via .find. Since panels are added dynamically there is no easy & clean way to add "data-test-id" and I really have a feeling that by using "data-test-id" my test will not capture original intent "widget inside specific panel"

As a potential solution, WDYT of adding to findComponent, findAllComponents selector second argument, context (absolutely similar to jquery approach where you can write $('tr', '.panel')) which will allow us to filter components located under specific DOM vnode

This API is not forward compatible with Vue 3 + VTU v2 iirc - thus the deprecation. You cannot find a vnode from a DOM component, according to this comment. findComponent(Foo).find('#dom-el') is trivial to implement, but not the opposite way, since find returns a DOMWrapper (no vnode). From there is no way back to the VDOM (apparently, I didn't implement this part of the code-base).

I am not exactly why this isn't forward compatible with Vue 3, since obviously it does work here. The VDOM implementation changed a lot in Vue 2 -> Vue 3, maybe that is why? I have not personally looked into it, since I am a fan of making the separation between testing the DOM output (via find) and implementation details (via findComponent) clear.

If we can support chaining both ways in V2, it would be fine to allow chaining both find and findComponent (in both orders, I think it would feel a bit dirty if we only supported one way chaining and not the other).

You could try implementing this in V2, to see if it's really not forward compatible. The relevant file is here, it is pretty confusing, though 馃槄 WDYT?

@lmiller1990 will be happy to try :+1:

Was this page helpful?
0 / 5 - 0 ratings