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

Checking style rules using Jest matchers #146

Closed
santino opened this issue Jun 12, 2018 · 5 comments
Closed

Checking style rules using Jest matchers #146

santino opened this issue Jun 12, 2018 · 5 comments

Comments

@santino
Copy link
Contributor

santino commented Jun 12, 2018

In Jest the expect function has many powerful matchers to work with objects, arrays and string.

You can easily make an assertion like this


expect('my custom string').toEqual(expect.stringContaining('custom'))

.toHaveStyleRule works with strings; it fetches the style (as a string) applied to a specific rule.
Sometimes the props passed to a component are affecting the styles applied to specific rules and it would be great to use the Jest matchers rather than just doing a comparison against the entire value.

Take the following rule example:


border: 0.05em solid ${({transparent}) => transparent ? 'transparent' : 'black'};


In my test case scenario I want to check the default styling like so:

expect(component).toHaveStyleRule('border', '0.05em solid black')

And later on I want to have another test to check the variation given a passed prop (in this case "transparent").

However this prop only changes the colour of my border so I don’t want to test against the border-width nor border-style as these are core styles that I’m already testing with my default styling assertion above.
This is what I want to do:

expect(component).toHaveStyleRule('border', expect.stringContaining('transparent'))

This is just one use case but there are definitely more scenarios where Jest matchers might be useful.
For example given this rule


opacity: ${({ disabled }) => disabled && '.65'};

I want to test that by default (when not passing the "disabled" prop) my component doesn't have any opacity rule applied; with Jest matchers I could do this with either one of the following assertions:


expect(component).not.toHaveStyleRule('opacity', expect.anything())

expect(component).not.toHaveStyleRule('opacity', expect.any(String))

But this is currently not supported by .toHaveStyleRule as it expects a string to compare against the style rule.


A different way of achieving this, which might mitigate the additional responsibility for this module, would be to add a complimentary function to .toHaveStyleRule.
A function named .styleRule, for example, could just be responsible for returning a string with the style applied to a given rule and then the Jest API can be used to apply any matching logic.

Here is an example of what this could look like:

expect(component.styleRule('border')).toEqual(expect.stringContaining('transparent'))

expect(component.styleRule('opacity')).toBeUndefined() // or .toBeNull() || .toBeFalsy()


Obviously this should take the same arguments of .toHaveStyleRule and so we should be able to pass modifiers and media.

@MicheleBertoli
Copy link
Member

Thank you very much @santino for opening this issue.

Although is currently possible to achieve some of the behaviours you described using a regex, I really like the solution you suggested.

Do you have time to work on a PR?
I'll be happy to review it.

@santino
Copy link
Contributor Author

santino commented Jun 20, 2018

Hi @MicheleBertoli,
I have been looking into this and unfortunately the .styleRule approach is not feasible.

In order to have something like this


expect(component.styleRule('border')).toBe(‘something’)

styleRule would need to be a method in Enzyme and/or react-test-renderer.

Even the following approach wouldn’t work


expect(component).styleRule('border').toBe(‘something’)

Because Jest does allow creation of custom matchers but they can’t return a string; since they are matchers (and so need to implement a matching logic) they need to return an object with pass and message properties.

Given the above I went back to the original approach of supporting the jest asymmetric matchers and I will create a PR soon.
My goal is to support something like the following examples:

expect(component).toHaveStyleRule(‘border’, expect.stringContaining('transparent'))

expect(component).not.toHaveStyleRule('opacity', expect.any(String))

I have a working prototype that just needs some polishing.

Unfortunately I don’t have experience with React Native so someone else will possibly have to port my changes onto the React Native implementation of .toHaveStyleRule.

@santino
Copy link
Contributor Author

santino commented Jun 21, 2018

@MicheleBertoli I have now opened the pull request and I have implemented the changes also for React Native.
Hope you can review it soon as I'm keen to start using the new functionalities :)

@santino
Copy link
Contributor Author

santino commented Jul 1, 2018

Hey @MicheleBertoli, sorry for opening this issue again.

I was just wondering when you were planning to publish a new release to include the new features addressed following this issue.
It's been a while now and I would really need to update my project making use of Jest asymmetric matchers.

Thanks :)

@MicheleBertoli
Copy link
Member

Hey @santino,
I was waiting for a couple of issues (e.g. #135) to be closed and to find time for cleaning up a few things (e.g. Eslint VS Prettier) before pushing a new major.

However, I can see the value of using the current master with your changes, so I pushed: jest-styled-components@6.0.0-0.

Feel free to install it using yarn add --dev jest-styled-components@next.

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

No branches or pull requests

2 participants