testing-library / vue-testing-library

🦎 Simple and complete Vue.js testing utilities that encourage good testing practices.
http://testing-library.com/vue
MIT License
1.08k stars 109 forks source link

@testing library/Vue Can you provide APIs for obtaining component props, data and slots? #249

Closed yibird closed 3 years ago

yibird commented 3 years ago

Hello, library maintainer, I just used this library. Maybe it's my personal problem (I'm a novice). Compared with the library @ Vue / test utils, @ testing library / Vue is more confusing. For example, the following example of testing component props:

<template>
<div>
<span>{{ message }}</span>
</div>
</template>
<script setup lang="ts">
interface Props {
messag
}
defineProps<Props>();
</script>

The test cases corresponding to @ testing library / Vue are as follows:

test("test01:test Header.vue props", () => {

const { getByText } = render(Header, {

props: {

message: "hello",

},

});

expect(getByText("hello").innerText).toBe("hello");

});

The above problem is to obtain elements through text content. Assuming that there are other elements with Hello text content in the header.vue component, the test will fail. For example, the header.vue template is:

<template>
<div>
<span>{{ message }}</span>
<span>hello</span>
</div>
</template>

I think it is limited to obtain elements through some content or identification through find , get , query * APIs. The library should provide an instance to obtain component API, and the method to obtain data, props, slots and other information on the component instance, which is easier to test. I don't know whether my suggestion can be accepted, but I think it should develop in a good direction. Maybe I'm wrong.

afontcu commented 3 years ago

Hi!

Vue Testing Library is built on top of the official Vue Test Utils, and it offers a different set of queries and methods to interact with your component – queries that focus on the user that would interact with the component instead of relying on internals.

For this, this is what the test you shared above would look in Vue Testing Library:

test("test01:test Header.vue props", () => {
  const { getByText } = render(Header, {
    props: {
      message: "hello",
    },
  });

  expect(getByText("hello")).toBe(true);
  /* 
    getByText() automatically fails if it is unable to find the element, so 
    simply checking if it returns is good enough.

    If you install jest-dom, you can also write the following, which is much more explicit:
  */

  expect(getByText("hello")).toBeInTheDocument();
});

You have a similar examples in the Introduction docs.

The above problem is to obtain elements through text content. Assuming that there are other elements with Hello text content in the header.vue component, the test will fail

This is by design (docs). If you expect several elements with the same text, you could:

1) Use getAllByText, which returns an array. 2) Use more semantic queries such as getByRole (something that differentiates both text strings).

The library should provide an instance to obtain component API, and the method to obtain data, props, slots and other information on the component instance, which is easier to test

As I mentioned, this won't happen – this is what Vue Testing Library wants to avoid people from doing. We want people to focus on component outputs, not internals.

However, if you still want to access internals, Vue Test Utils will provide the appropriate methods to do so.

Hope this helped!