Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with multi-root components utilizing <script setup> #550

Closed
AndreasNasman opened this issue Apr 26, 2021 · 3 comments
Closed

Problems with multi-root components utilizing <script setup> #550

AndreasNasman opened this issue Apr 26, 2021 · 3 comments
Labels
discussion enhancement New feature or request

Comments

@AndreasNasman
Copy link

AndreasNasman commented Apr 26, 2021

Hi!

I tried creating some snapshot tests based on the example test file merged in #264.

<!-- Hello.vue -->
<template>
  <div>{{ msg }}</div>
  <div>
    <button @click="incrementCount">{{ count }}</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "Hello",
  setup() {
    const msg = ref("Hello world");
    const count = ref(0);
    const incrementCount = () => {
      count.value++;
    };

    return {
      count,
      incrementCount,
      msg,
    };
  },
});
</script>

Same as Hello.vue using <script setup>.

<!-- ScriptSetup.vue -->
<template>
  <div>{{ msg }}</div>
  <div>
    <button @click="incrementCount">{{ count }}</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";

const msg = ref("Hello world");
const count = ref(0);
const incrementCount = () => {
  count.value++;
};
</script>
// sfc.spec.js
import Hello from "@/components/Hello.vue";
import ScriptSetup from "@/components/ScriptSetup.vue";
import { mount } from "@vue/test-utils";

describe("sfc", () => {
  it("mounts an sfc via vue-test-transformer", async () => {
    const wrapper = mount(Hello);

    expect(wrapper.text()).toContain("Hello world");

    await wrapper.find("button").trigger("click");
    expect(wrapper.html()).toContain("1");

    expect(wrapper.html()).toMatchSnapshot();
    expect(wrapper.element).toMatchSnapshot();
  });

  // rfc: https://github.com/vuejs/rfcs/pull/228
  it("works with <script setup> (as of Vue 3.0.3)", async () => {
    const wrapper = mount(ScriptSetup);

    // This `expect` fails since `.text()` return an empty string!
    // expect(wrapper.text()).toContain("Hello world");

    await wrapper.find("button").trigger("click");
    expect(wrapper.html()).toContain("1");

    // Why does `.html()` produce a snapshot with content
    expect(wrapper.html()).toMatchSnapshot();
    // ...while `.element` result in an empty one?
    expect(wrapper.element).toMatchSnapshot();
  });
});
// sfc.spec.ts.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`sfc mounts an sfc via vue-test-transformer 1`] = `"<div>Hello world</div><div><button>1</button></div>"`;

exports[`sfc mounts an sfc via vue-test-transformer 2`] = `
<div
  data-v-app=""
>
  
  <div>
    Hello world
  </div>
  <div>
    <button>
      1
    </button>
  </div>
  
</div>
`;

exports[`sfc works with <script setup> (as of Vue 3.0.3) 1`] = `"<div>Hello world</div><div><button>1</button></div>"`;

exports[`sfc works with <script setup> (as of Vue 3.0.3) 2`] = ``;

My questions are

  1. Same as in the code comments: Why does calling .html() on the wrapper produce content while .element and .text() are empty in the test case with <script setup>? I think it's related to having multiple roots; if I wrap all the elements in the template of ScriptSetup in e.g. a div, both .html() and .element have content, also .text(). Could also be related to the issues mentioned in Not working with Vue 3.0.3 and latest <script setup> #263.
  2. A more general question: Should .html() or .element be used for snapshot testing? I've seen both and don't really know if one is better than the other or if they're more or less interchangeable.

Thanks!
– Andreas

@lmiller1990
Copy link
Member

Hi!

Good questions.

Why does calling .html() on the wrapper produce content while .element and .text() are empty in the test case with <script setup>

I don't know off the top of my head but I think your suspicion is probably correct (multiple roots). This codebase does not have many (any?) snapshots tests. We probably need to add some and define the expected behavior. Snapshots are normally formatted by a snapshot seralizer which can be opinionated. My guess is:

  • if you pass text (eg via html()) it will just save that.
  • if you pass a DOM element, Jest must have a default serializer that tries to grab innerHTML or outerHTML.

This means, in practice, they are more or less interchangable, but they are not guaranteed to give the exact same results.

In terms of actionable content here, I think what we should do is:

  • create a new test file, maybe tests/features/snapshots.spec.ts
  • come up with all the edge cases (looks like you did that already)
  • figure out the desired output, make sure everything works as expected. I'm mainly concerned with the bugs around <script setup> and no root nodes.

Is this something you'd like to work on? Just adding the tests would be great, we can discuss the behavior once we have a good set of tests to establish the current vs desired behavior. We could even provide a simple snapshot serializer, too.

@lmiller1990 lmiller1990 added discussion enhancement New feature or request labels Apr 27, 2021
@AndreasNasman
Copy link
Author

Hi, and thanks for your answers!

I'm more than happy to try my hands at adding relevant tests, I might have some free time later this week. 👍

@AndreasNasman AndreasNasman changed the title toMatchSnapshot with <script setup> Problems with multi-root components utilizing <script setup> May 15, 2021
@AndreasNasman
Copy link
Author

Sorry I never had the time to look more into this issue! Seem to be resolved in v2.0.0-rc.16! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants