Skip to content

Documentation for testing a component without resolving sub-components #497

@lambdalisue

Description

@lambdalisue

What problem does this feature solve?

Intro

Assume that there are two components, <x-icon> and <x-checkbox>.

The <x-icon> component is for showing a font icon given by face="..." attributes like

<x-icon face="error"/>              <!-- It shows an error icon -->
<x-icon face="checkbox-empty"/>     <!-- It shows a checkbox empty icon -->
<x-icon face="checkbox-checked"/>   <!-- It shows a checkbox checked icon -->

And <x-checkbox> uses <x-icon> with face attribute like

<div class="checkbox">
    <x-icon :face="face"/>  <!-- 'face' attributes are internal and linked to 'checked' attribute -->
    <input v-model="checked" type="checkbox">
</div>

So the final HTML will be one of the followings (without resolving <x-icon>)

<div class="checkbox">
    <x-icon face="checkbox-empty"/>
    <input  type="checkbox">
</div>

<!-- or -->

<div class="checkbox">
    <x-icon face="checkbox-checked"/>
    <input type="checkbox" checked>
</div>

What I would like to do

I would like to test <x-checkbox> component without understanding an implementation of the <x-icon>.
For example, I would like to check

  1. Is initial HTML shows <x-icon face="checkbox-empty">
  2. Is HTML shows <x-icon face="checkbox-checked"> after <x-checkbox> has clicked.

For this purpose, I cannot use stubs: { 'x-icon': true } while

  1. x-icon is defined in components attributes of x-checkbox component and in this case, stubs seems ignored.
  2. stubs creates an empty comment so I cannot check if the component is x-icon or not
  3. stubs removes attributes even I uses stubs: { 'x-icon': SomeThing } so I cannot check if the component attributes of x-icon has correctly changed

What does the proposed API look like?

I'm not really proposing but currently, I use a wrapper function to

  1. Overwrite localVue.config.isUnknownElement function to allow elements in components
  2. Remove components to prevent element resolving

like

import { mount as mountBase } from '@vue/test-utils';

const original = Vue.config.isUnknownElement;

export function mount(component: any, options: any= {}) {
  const localVue = options.localVue || createLocalVue();
  if (!!component.options && !!component.options.components) {
    const ignoredElements = Object.keys(component.options.components);
    Vue.config.isUnknownElement = (tag: string): boolean => {
      if (ignoredElements.includes(tag)) {
        return false;
      }
      return original(tag);
    }
    component.options.components = {};
  }
  return mountBase(component, {
    ...options,
    localVue,
  });
}

Is this a correct way?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions