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

Feature Request: Type-Specific Matchers with Fallback and Inheritance Support in expect #1651

Open
dvegap95 opened this issue Oct 18, 2024 · 0 comments

Comments

@dvegap95
Copy link

dvegap95 commented Oct 18, 2024

Summary:
I am requesting support for extending matchers in expect for specific types passed as arguments, with fallback to matchers based on inheritance hierarchies. This ensures that custom objects and UI components can have specialized matchers, with fallbacks going through the inheritance chain and then defaulting to matchers defined without any class.

Detailed Explanation:
I often use the pageComponentObject pattern for testing UI components in React applications with Vitest and Testing Library. In my use case, I want to define custom matchers for certain types, like ButtonTestObject, with fallbacks based on inheritance. Additionally, it would be beneficial for custom matchers to have access to existing matchers that were declared via expect.extend, allowing for flexibility and clarity in the assertion process.

For example, I want to check if a custom button is disabled by verifying it has the class disabled whereas keeping the posibility to use the already extended matcher of testing library. Here’s a simple illustration of what I’m aiming for:

expect.extend(ButtonTestObject, {
  toBeDisabled(target) {
    const { matchers: { toHaveClass, toBeDisabled } } = this;// This is just an illustrative example
    const byClass = toHaveClass.call(this, target.root, 'disabled');
    if(byClass.pass) return byClass // already disabled, no need for further checks
    // fallback to the default disabled check of testing library, which checks for the disabled attribute
    return toBeDisabled(this.root) 
  }
});

Real Use Cases:

  1. toBeLoading() over a ViewTestObject Base Class: When testing a loading state, toBeLoading() could check for the existence of a skeleton component. In a derived class from ViewTestObject, toBeLoading() would instead check for a progress bar, allowing for type-specific loading assertions.

  2. Modals: When testing modals, toBeOpen() could determine if a modal is open based on whether the specific instance is rendered conditionally or simply set to display: none, depending on the modal type. This creates flexibility in how we assert modal states.

Key Features:

  1. Type-Specific Matchers: Matchers should be extendable for specific types passed to expect.

  2. Access to Existing Matchers: Custom matchers should have access to the matchers already declared via expect.extend, allowing for potential interactions and fallbacks.

  3. Inheritance-Based Fallback: If a custom matcher is not found for a specific type, the fallback should go through the inheritance chain (e.g., a ButtonTestObject falling back to its base class), eventually reaching the matchers declared without any specific class (the current behavior).

  4. Inheritance Support: If an object extends from ButtonTestObject, it should still work with the same custom matchers and those of its parent class.

  5. Integration with Existing Matchers: The solution should integrate seamlessly with existing matchers (e.g., those from external libraries like Testing Library).

Advantages:

  • Improved Test Clarity: By using this approach, tests can become significantly cleaner. Instead of executing multiple procedures to assert something and providing lengthy comments on how the assertions meet the test objectives, you would have a single line with a descriptive assertion. This line can also be tailored to the specific context of what you’re testing, making the intent clear and concise.

Why This Feature is Needed:

This feature would improve flexibility when testing custom objects and UI components. For example, in my current project, I need to determine whether a button is disabled based on a class name. Having type-specific matchers with inheritance-based fallback allows more control over custom components and ensures matchers work appropriately in complex inheritance scenarios.

Potential Solutions:

I’ve implemented a workaround in my project, but it lacks the robustness that integrating this feature into the core library would provide. If this functionality already exists and I’m unaware, please let me know.

Disclamer:

This is my first Feature Request ever, despite I've been developing many years now, so any feedback will be appreciated, also forgive my english, i'm not native. Also couldn't find a template, i hope this would do.

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

No branches or pull requests

1 participant