如何给lit框架构建的组件库选择单元测试框架

最近给公司的Lit框架构建的组件库去选型单元测试框架,有了一些总结。

首先,网上大多数的Lit组件都是用@open-wc/testing这个框架,但是实际用下来发现还是不太好用,语法与流行的Jest等测试框架不是很兼容,文档也不是很全,需要自己去找一些插件去配合。

最后,通过对比和分析,还是选择了Vite的 Vitest测试框架。我把选型的过程给大家分享出来一下。

自动化测试概念

大家先了解一些自动化测试的概念,重点看一下单元测试使用的流行的框架,从它们的创建人和历史的来龙去脉就能够所见端倪。 很多人以为测试框架都是差不多的,比如流行的Mocha框架和Jest框架,从它们的创建公司和创建人就能够明白,这两个框架适用的工程场景了。

概念.jpg

选型

选型从几个角度来看,文档是否齐全、社区是否活跃、框架维护的人多不多、开发效率高不高、是否适合你的项目。最后我们的Lit框架组件库,还是比较适合用Vitest测试框架来进行单元测试的。

选型.jpg

示例代码

import { page, userEvent } from '@vitest/browser/context'
import { beforeEach, describe, expect, test } from "vitest"

import "../../index.css"
import "../checkbox"
import "../checkboxGroup/checkboxGroup"

async function render(html) {
    document.body.innerHTML = html;
    await new Promise(resolve => setTimeout(resolve, 0));
}

describe('Bee Checkbox', async () => {

    function getCheckboxEl(): HTMLElement {
        return document.querySelector('bee-checkbox')
    }

    function getCheckboxGroupEl(): HTMLElement {
        return document.querySelector('bee-checkbox-group')
    }

    test('create', async () => {
        await render('<bee-checkbox>腹部</bee-checkbox>')
        const checkbox = getCheckboxEl();
        const innerCheckbox = checkbox.querySelector('label');
        await userEvent.click(checkbox);
        expect(innerCheckbox.classList.contains("bee-checkbox--wrapper__checked")).toBe(true);
        await userEvent.click(checkbox);
        expect(innerCheckbox.classList.contains("bee-checkbox--wrapper__checked")).toBe(false);
    })

    test('disabled', async () => {
        await render('<bee-checkbox disabled>腹部</bee-checkbox>')
        const checkbox = getCheckboxEl();
        const innerCheckbox = checkbox.querySelector('label');
        expect(innerCheckbox.classList.contains("bee-checkbox__disabled")).toBe(true);
        await userEvent.click(checkbox);
        expect(innerCheckbox.classList.contains("checkbox__disabled")).toBe(false);
    })


    test('change', async () => {
        await render('<bee-checkbox>腹部</bee-checkbox>')
        const checkbox = getCheckboxEl();
        let checkData = null;
        checkbox.addEventListener('change', (e: CustomEvent) => {
            checkData = e.detail;
        })
        await userEvent.click(checkbox);
        expect(checkData).toBe(true)
    })

    describe('Bee Checkbox', async () => {
        test('checkbox group', async () => {
            await render(`<bee-checkbox-group>
            <bee-checkbox label="腹部"></bee-checkbox>
            <bee-checkbox label="胸部"></bee-checkbox>
            <bee-checkbox label="头部"></bee-checkbox>
            </bee-checkbox-group>`)
            const checkboxGroup = getCheckboxGroupEl();
            checkboxGroup['value'] = ['腹部'];
            const checkboxElement = document.querySelector('bee-checkbox[label="腹部"]');
            const innerCheckbox = checkboxElement.querySelector('label');
            await waitRender();
            expect(innerCheckbox.classList.contains("bee-checkbox--wrapper__checked")).toBe(true);
        })

        test('checkbox group min and max', async () => {
            await render(`<bee-checkbox-group min=1 max=3>
            <bee-checkbox label="腹部"></bee-checkbox>
            <bee-checkbox label="胸部"></bee-checkbox>
            <bee-checkbox label="头部"></bee-checkbox>
            <bee-checkbox label="足部"></bee-checkbox>
            </bee-checkbox-group>`)
            const checkboxGroup = getCheckboxGroupEl();
            checkboxGroup['value'] = ['腹部'];

            await userEvent.click(document.querySelector('bee-checkbox[label="腹部"]'));
            expect(checkboxGroup['value'].length).toBe(1);
            await userEvent.click(document.querySelector('bee-checkbox[label="胸部"]'));
            expect(checkboxGroup['value'].length).toBe(2);
            await userEvent.click(document.querySelector('bee-checkbox[label="头部"]'));
            expect(checkboxGroup['value'].length).toBe(3);
            await userEvent.click(document.querySelector('bee-checkbox[label="足部"]'));
            expect(checkboxGroup['value'].length).toBe(3);
        })

        test('checkbox group disabled', async () => {
            await render(`<bee-checkbox-group disabled>
            <bee-checkbox label="腹部"></bee-checkbox>
            <bee-checkbox label="胸部"></bee-checkbox>
            <bee-checkbox label="头部"></bee-checkbox>
            </bee-checkbox-group>`)
            const checkboxGroup = getCheckboxGroupEl();
            checkboxGroup['value'] = ['腹部','胸部','头部'];
            await userEvent.click(document.querySelector('bee-checkbox[label="腹部"]'));
            expect(checkboxGroup['value'].length).toBe(3);
            expect(checkboxGroup.firstElementChild.classList.contains("bee-checkbox-group__disabled")).toBe(true);
        })

        test('checkbox group marked', async () => {
            await render(`<bee-checkbox-group>
            <bee-checkbox label="腹部" marked></bee-checkbox>
            <bee-checkbox label="胸部"></bee-checkbox>
            <bee-checkbox label="头部"></bee-checkbox>
            </bee-checkbox-group>`)
            const checkboxGroup = getCheckboxGroupEl();
            checkboxGroup['value'] = ['腹部','胸部','头部'];
            const checkboxElement = document.querySelector('bee-checkbox[label="腹部"]');
            const innerCheckbox = checkboxElement.querySelector('label');
            expect(innerCheckbox.classList.contains("bee-checkbox__marked")).toBe(true);
        })

        test('checkbox group vertical', async () => {
            await render(`<bee-checkbox-group direction="vertical">
            <bee-checkbox label="腹部" marked></bee-checkbox>
            <bee-checkbox label="胸部"></bee-checkbox>
            <bee-checkbox label="头部"></bee-checkbox>
            </bee-checkbox-group>`)
            const checkboxGroup = getCheckboxGroupEl();
            expect(checkboxGroup.firstElementChild.classList.contains("bee-checkbox-group--wrapper__vertical")).toBe(true);
        })

    })
})

async function waitRender() {
    await new Promise(resolve => setTimeout(resolve, 0));
}
Written on December 20, 2024