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

[Component] [Form] Import { ElForm, ElFormItem } from "element-plus" write unit test validate is incorrect #15053

Open
lequangdongg opened this issue Dec 5, 2023 · 9 comments
Labels

Comments

@lequangdongg
Copy link
Contributor

lequangdongg commented Dec 5, 2023

Bug Type: Component

Environment

  • Vue Version: 3.2.27
  • Element Plus Version: 2.4.3
  • Browser / OS: Version 104.0.5112.79 (Official Build) (x86_64)
  • Build Tool: Vite

Reproduction

Related Component

  • el-form
  • el-form-item

Steps to reproduce

import from 'element-plus' form validate incorrect
288007370-e93d6da9-7705-4d8f-bb25-18517dbb1c23

Screenshot 2023-12-05 at 5 32 43 PM de0-44e3-b548-e8e96a2523fb">

It will be correct when imported as is
Screenshot 2023-12-05 at 5 30 53 PM

What is Expected?

Unit test form validate correct

What is actually happening?

validate incorrect

Additional comments

(empty)

@lequangdongg lequangdongg changed the title [Component] [form, form-item] [Component] [Form] Import { ElForm, ElFormItem } from "element-plus" write UT validate is incorrect [Component] [Form] Import { ElForm, ElFormItem } from "element-plus" write UT validate is incorrect Dec 5, 2023
@lequangdongg lequangdongg changed the title [Component] [Form] Import { ElForm, ElFormItem } from "element-plus" write UT validate is incorrect [Component] [Form] Import { ElForm, ElFormItem } from "element-plus" write unit test validate is incorrect Dec 5, 2023
@cuongle-hdwebsoft
Copy link
Contributor

Hi @lequangdongg,
It seems like your branch is out of date. Here is the newest code in the release branch. Besides that, I've run the test locally and there is no error. Could you please check again?

@lequangdongg
Copy link
Contributor Author

Thanks @cuongle-hdwebsoft, currently I am using the latest branch
If imported as latest code in release branch it will pass, but if imported { ElForm, ElFormItem } from 'element-plus' it will fail

@cuongle-hdwebsoft
Copy link
Contributor

cuongle-hdwebsoft commented Dec 11, 2023

Why you don't use @element-plus? @lequangdongg

@cuongle-hdwebsoft
Copy link
Contributor

I realize that you are installing element-plus from somewhere and using that in library source

@lequangdongg
Copy link
Contributor Author

Why you don't use @element-plus? @lequangdongg

I understand but if replace
import ElForm from ‘../src/form import ElFormItem from ../src/formitem
to
import { ElForm, ElFormItem } from ‘element-plus’
result formRef.validate the promise always goes into the then case

@lequangdongg
Copy link
Contributor Author

when i write UT with form in my source code it won't be as i expected

@cuongle-hdwebsoft
Copy link
Contributor

cuongle-hdwebsoft commented Dec 11, 2023

Installing element-plus in element-plus source is not the correct way to test your bug. There may be @element-plus/components/form/src/form.vue or @element-plus/components/form/src/form-item.vue, I even cannot install element-plus without modifying the config. If your unit test does not work as expected, you should show your example code on how you test with these components in your source (not Element Plus) and what error you got from that code.

@lequangdongg
Copy link
Contributor Author

lequangdongg commented Dec 11, 2023

This is example code

import { reactive, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
import { ElForm, ElFormItem, type FormInstance, Input } from 'element-plus'

describe('Form', () => {
  it('show message', async () => {
    const form = reactive({
      name: '',
    })
    const formRef = ref<FormInstance>()
    const wrapper = mount(() => (
      <ElForm model={form} ref={formRef}>
        <ElFormItem
          prop="name"
          showMessage={false}
          rules={{
            required: true,
            message: 'Please input name',
            trigger: 'change',
            min: 3,
            max: 6,
          }}
        >
          <Input v-model={form.name} />
        </ElFormItem>
      </ElForm>
    ))
    vi.useFakeTimers()
    const valid = await formRef.value
      .validate()
      .then(() => true)
      .catch(() => false)
    vi.runAllTimers()
    vi.useRealTimers()
    expect(valid).toBe(false)
  })
})

my expected, it must go into catch

@cuongle-hdwebsoft
Copy link
Contributor

cuongle-hdwebsoft commented Dec 13, 2023

Hi @lequangdongg, here is my reproduced code

index.test.ts

import { reactive, ref } from "vue";
import { mount } from "@vue/test-utils";
import { describe, expect, it, vi } from "vitest";
import { ElForm, ElFormItem, type FormInstance, ElInput } from "element-plus";
import MyComponent from "./MyComponent.vue";

describe("Form", () => {
  it("show message", async () => {
    const form = reactive({
      name: "",
    });
    const wrapper = mount(MyComponent, {
      global: {
        components: {
          "el-form": ElForm,
          "el-form-item": ElFormItem,
          "el-input": ElInput,
        },
        stubs: {
          teleport: true,
        },
      },
      data: () => {
        return {
          form: {
            name: "",
          },
        };
      },
    });

    const valid = await wrapper.vm.formRef
      .validate()
      .then(() => true)
      .catch(() => false);

    console.log("valid", valid);

    expect(valid).toBe(false);
  });
});

MyComponent.vue

<template>
  <el-form :rules="rules" :model="form" ref="formRef">
    <el-form-item prop="name">
      <el-input v-model="form.name" />
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ElForm, ElFormItem, ElInput, ElButton } from 'element-plus'
import { reactive, ref } from 'vue';

const form = reactive({
  name: ''
})

const formRef = ref()

const rules = reactive({
  name: [
    {
      required: true, message: "Please input name", trigger: 'blur'
    },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ]
})

defineExpose({
  formRef
})
</script>

If you go to node_modules/element-plus/es/components/form/src/form-item2.mjs, In validate If you print the error, you will receive TypeError: AsyncValidator is not a constructor

CleanShot 2023-12-13 at 16 58 27@2x

Look atdoValidate function at the above file path, and change AsyncValidator to AsyncValidator.default

CleanShot 2023-12-13 at 17 02 23@2x

Once you change it, run that test again, and your valid will be false. The way I did that is not a solution, but that's all thing I can explain to you

You can find out about this issue here more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants