3 个版本 (破坏性更新)

0.3.0 2024年1月4日
0.2.0 2022年3月8日
0.1.0 2022年3月6日

WebAssembly 中排名 #279

MIT/Apache

43KB
457

Frontest

Crates.io docs.rs tests status downloads licenses

一个轻量级的库,用于查询和断言 DOM。

Frontest 严重受到了 dom-testing-libraryreact-testing-library 的启发。它提供了一套查询,您可以使用这些查询快速找到文档中的元素,同时考虑到可访问性优先级。

示例

use frontest::prelude::*;
use gloo::utils::{body, document};

let div = document().create_element("div").unwrap();
div.set_inner_html(
    r#"<div>
        <label>
            I will start testing my frontend!
            <button>
                Take the red pill
            </button>
        </label>
        <label>
            It's too problematic dude...
            <button>
                Take the blue pill
            </button>
        </label>
    </div>"#,
);
body().append_child(&div).unwrap();

let go_to_matrix = div
    .get(&HasRole("button").and(Not(HasLabel("It's too problematic dude..."))))
    .unwrap();
go_to_matrix.click();

body().remove_child(&div).unwrap();

关于测试

这个库旨在允许开发人员以用户交互的方式测试他们的应用程序。为此,建议将某些查询优先于其他查询。目前只实现了两个匹配器。未来版本中将提供更多匹配器。匹配器应按以下顺序优先级使用

  • HasRole 应尽可能使用。它允许访问可暴露到可访问性树中的元素。
  • HasLabel 也应尽可能使用。它受屏幕阅读器支持,并允许更容易地聚焦元素。
  • HasPlaceholder 不如前两者好,然而对于可访问元素来说,仍然比 HasText 更好。
  • HasText 可以用来选择非交互式组件或进一步限制其他查询。

匹配器

匹配器是 HtmlElement 的谓词。如果给定的元素满足某些标准,则返回 true,否则返回 false

通过使用匹配器 NotJoinable 特性中的方法,可以将多个匹配器组合成一个逻辑表达式。

您可以轻松实现自己的 Matcher

struct IsHidden;

impl Matcher for IsHidden {
    fn matches(&self, elem: &HtmlElement) -> bool {
        elem.hidden()
    }
}

let div = document().create_element("div").unwrap();
div.set_inner_html(
    r#"<button hidden>
        Yayyy frontend in rust!
    </button>"#
);
div.append_child(&div).unwrap();

assert!(div.get(&IsHidden).is_some());

body().remove_child(&div).unwrap();

集成

应使用 wasm-bindgen-test 运行测试。它允许在浏览器或 node-js 中直接运行测试。

目前这个 crate 提供了一个 render 函数,允许快速渲染使用 yew 创建的任何 html。选择渲染 html 而不是直接获取组件是为了更容易地将它们包装在 ContextProvider 等等中。

示例

#[function_component(Incrementable)]
fn incrementable() -> Html {
    let counter = use_state(|| 0);
    let onclick = {
        let counter = counter.clone();
        Callback::from(move |_| counter.set(*counter + 1))
    };
    html! {
        <div>
            <p>{ format!("Value: {}", *counter) }</p>
            <button {onclick}>{ "Add" }</button>
        </div>
    }
}

use frontest::prelude::*;
use frontest::yew::render;

#[wasm_bindgen_test]
async fn clicking_on_button_should_increment_value() {
    let mount = render(html! { <Incrementable /> }).await;
    let value = mount.get(&HasText("Value:")).unwrap();
    let button = mount.get(&HasRole("button")).unwrap();

    assert_eq!("Value: 0", value.inner_text());
    button.click();
    assert_eq!("Value: 1", value.inner_text());

    body().remove_child(&mount).unwrap();
}

警告

wasm-bindgen-test 顺序运行所有测试并允许它们操作真实的DOM。然而,它不会为每个测试重新创建完整的DOM,因此一个测试中执行的操作可能会影响到其他测试。务必确保在测试后进行适当的DOM清理,例如删除挂载的子元素。希望在未来这个库能够提供某种类型的RAII来运行测试。

依赖项

约12-17MB
约293K SLoC