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

feat: add support to assert styles on states (hover, active) and media queries #168

Merged
merged 13 commits into from
Apr 26, 2020

Conversation

ankeetmaini
Copy link
Contributor

Fixes #138. Let me know if this approach looks okay.

@itsdouges
Copy link
Collaborator

hey mate thanks for throwing this PR up! I'll have a look

what's your thoughts on the API? I just threw something into the issue but I didn't really think about it.

const containsClassNames = (classNames: string[], css: string) =>
classNames.reduce((accum, className) => (css.includes(`.${className}`) ? true : accum), false);

// sorry but using ? was throwing TS off
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ? after MatchFilter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

let matcher = c;
if (state) matcher += `:${state}`;
if (media) matcher = `${media}{.*${matcher}`;
if (css.match(matcher)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means if there is no matcher defined it will just mark all styles it finds as assertable yeah?

what's your thoughts on this? i can see two sides to it

  • it might give false positives so people think something is working when it isnt
  • we treat matchers as narrowing and its ok that the default case asserts on every state

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing. I think a better approach would be to not do a text search and to convert this into an AST and then work with rules. This is done both in emotion-jest and styled-component jest matchers.

Also, at least in jest-styled-components matchers are mandatory and it doesn't work without narrowing, which I like too!

Let me know your thoughts and I can give it a spin.

Copy link
Collaborator

@itsdouges itsdouges Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like it - let's give it a spin

i prefer explicit over implicit.

maybe we can also do some dev tooling help such as if we find what they're looking for in a state they haven't chosen suggest maybe looking there (can be done in another PR!)

@ankeetmaini
Copy link
Contributor Author

@Madou this is ready for review now!

toHaveCompiledCss(
property: string,
value: string,
matchFilter?: Partial<Record<'state' | 'media', string>>
Copy link
Collaborator

@itsdouges itsdouges Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can bring in Pseudos to make it a bit easier and then fallback to string?

import { Pseudos } from 'csstype';

type State = Pseudos;

it does mean though every state will be prefix with a colon however : - maybe thats ok. (should we handle adding one if its not there?)

should we rename state to something that encompasses other groups pseudo selectors as well? what's your thoughts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, state to 'selector' maybe? I'll try this and update

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Madou if we just use the value as Pseudos, TS will automatically suggest and add :, but then > :first-child this won't be a valid one.

Is there a way I can preserve the intellisense as well as adding string?

Pseudos | string is just string

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me check it out locally and look

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@itsdouges itsdouges Apr 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { Pseudos } from 'csstype';

/**
 * {} is used to enabled the compiler to not reduce Target down to a string.
 * This keeps both Pseduos intellisense working as well as then allowing us to define anything.
 * See: https://github.com/microsoft/TypeScript/issues/29729#issuecomment-460346421
 */
type AnyTarget = string & { _?: never };
type Target = Pseudos | AnyTarget;

export interface MatchFilter {
  target?: Target;
  media?: string;
}

this fixes it

@@ -1,3 +1,10 @@
import CSS from 'css';

type MatchFilter = Partial<Record<'state' | 'media', string>>;
Copy link
Collaborator

@itsdouges itsdouges Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these types are duplicated in src/index.tsx maybe we can make a types.tsx file?

@itsdouges
Copy link
Collaborator

itsdouges commented Apr 23, 2020

looks great man! really impressed. left a few comments 👍

as a side I need you to sign the contribution CLA - if you can have a read of https://github.com/atlassian-labs/compiled-css-in-js/blob/master/CONTRIBUTING.md and then sign "for individuals" will be great 👍

};

const allRules = getAllRules();
const klass = state ? `.${className}:${state}` : `.${className}`;
Copy link
Collaborator

@itsdouges itsdouges Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will we be able to assert or more complex selectors?

css={`
  > :first-child {
    color: red;
  }
`}

expect(element).toHaveCompiledCss('color', 'red', { state: '> :first-child' });

Does that work? If not should it? (maybe we need to rename state to selector.. or target.. or something..)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, let me try this as well

@itsdouges
Copy link
Collaborator

you've done a really great job!! ❤️

@itsdouges itsdouges merged commit b38c0d8 into atlassian-labs:master Apr 26, 2020
@ankeetmaini
Copy link
Contributor Author

Yay, thanks so much @Madou :D

@itsdouges
Copy link
Collaborator

no worries! thank you for doing the work 🤗

@ankeetmaini ankeetmaini deleted the improve-matching branch April 26, 2020 12:00
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

Successfully merging this pull request may close these issues.

Improve jest matcher to assert on different states
2 participants