Skip to content

Conversation

@G-Rath
Copy link
Collaborator

@G-Rath G-Rath commented Jul 23, 2019

@yatki I've stepped on your toes a little bit here - sorry about that 😬

@G-Rath
Copy link
Collaborator Author

G-Rath commented Jul 23, 2019

Ping me before you merge this - I'm been rewriting the last the rules, resulting in some super new generic-ish guards that might supersed this PR.

*/
export const isExpectCallWithNot = (
node: TSESTree.Node,
): node is JestExpectCallWithNotParent =>
Copy link
Contributor

Choose a reason for hiding this comment

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

JestExpectCallWithNotParent looks like a Call without parent. Don't you think ExpectNotCall is a better naming @G-Rath :) Also we could avoid conflicts :D

Copy link
Collaborator Author

@G-Rath G-Rath Jul 23, 2019

Choose a reason for hiding this comment

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

Maybe? iirc I don't think b/c the parent is the Not.

I've actually spent the whole day pretty much writing a completely typesafe implementation of the guards that are also completely compatible w/ identifiers, literals and template literals, and am now converting the remaining rules right now.

I hope to push them up pretty soon, but they're still somewhat messy.

There was always going to be naming conflicts unfortunately.

Just to give you a little taste of the new guards in action:

const fn2 = (node: TSESTree.Node) => {
  if (
    isExpectCallWithSpecificParent(node, 'not') &&
    isExpectCallWithSpecificGrandParent(node, 'toBe')
  ) {
    if (getAccessorExpressionValue(node.parent.parent.property) === 'not') {
        // ^^ TS error - this will never be true
    }
    
    if (getAccessorExpressionValue(node.parent.property) === 'resolves') {
    }

    if (getAccessorExpressionValue(node.parent.parent.property) === 'toBe') {
    }
  }
};

Copy link
Contributor

Choose a reason for hiding this comment

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

oh looks nice.. Ok, no worries. Keep doing what you think is the best. As long as @SimenB is ok with these changes, later I can refactor my PR accordingly. 🖖

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No problem :)

Your PR was a huge help, as it helped confirm a lot of things I wanted to confirm before trying to rewrite all the guards.

Would it be ok if I pulled your PR into mine? Just in case I need to to hit 100% coverage & ensure the guards are all correct.

I'm definitely going to want as many eyes as I can on it, as there's definitely redundancy, so I'll make sure to ping you when I push up a draft PR (which I might be doing very soon).

Copy link
Member

Choose a reason for hiding this comment

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

I don't really have an opinion either way. In general I'd like to avoid the parent terminology since I find it weird. But I think we should use it for now since it represents the AST nodes, and keeping the names correct makes it easier to reason about. Once we've ported all rules and we've got strong type safety in the utils, I'd like to revisit #73 (comment). So you can some kind of custom structure back and instead of accessing .parent (or .parent.parent in case of not) you just do .matcher and check a boolean .isNot or something.


Anyways, rambling way of saying "these names are fine for now, I'd like to revisit after migration is complete to see if we can simplify" 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I completely agree, and just you wait until you see some of the new names :D

Tbh, while the names seem to go against what we've taught as programmers, in AST land they're actually really nice - things like isExpectCallWithJestNamespace (here's a structural screenshot which contains about half the types & guards: http://puu.sh/DWjAi/e0a141eab4.png) that are actually really nicely verbose once you get use to using them in the land of AST where there's lots of annoying layers.

I do totally agree w/ the parent thing - it's super annoying, b/c I've not been able to think up of a better name that isn't less accurate or technically incorrect in some way :/

Copy link
Member

Choose a reason for hiding this comment

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

For sure, I think we should keep the verbose names as they more directly map to the underlying AST nodes we operate on. But down the line we can create more human readable abstractions on top of it to easily make assertions about different matchers (while still keeping the verbose versions as the implementation)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think that's exactly the right way to go about it, and what I've been working towards.

It's already how we're doing accessors now:

type SpecificAccessorExpression<Specifics extends string> =
  | SpecificStringNode<Specifics>
  | SpecificIdentifier<Specifics>;

type AccessorNode = SpecificAccessorExpression<string>;

const isSupportedAccessor = (node: TSESTree.Node): node is AccessorNode =>
  node.type === AST_NODE_TYPES.Identifier || isStringNode(node);

export const getAccessorExpressionValue = <S extends string = string>(
  accessor: SpecificAccessorExpression<S>,
): S =>
  accessor.type === AST_NODE_TYPES.Identifier
    ? accessor.name
    : getSpecificStringValue(accessor);

*
* @return {node is JestExpectCallWithNotParent}
*/
export const isExpectCallWithNot = (
Copy link
Member

Choose a reason for hiding this comment

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

could possibly have a version with this that receives a JestExpectCallWithParent which just checks the parent? in this rule, we call isExpectCallWithParent twice. Probably not a big issue as the checks are pretty cheap

Copy link
Member

@SimenB SimenB left a comment

Choose a reason for hiding this comment

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

LGTM. Can hold off on merge if you want @G-Rath?

@G-Rath
Copy link
Collaborator Author

G-Rath commented Jul 23, 2019

@SimenB yes please - I'm going to make a WIP PR very soon I think, so that you can start picking it to bits while I'm still working on it :P

@G-Rath
Copy link
Collaborator Author

G-Rath commented Jul 23, 2019

btw @yatki something you could do that'd be a huge help would be to figure out how to get the getToken<Before/After> & get<First/Last>Token methods on SourceCode to return null, so that we can test them.

Right now we just have istanbul ignore the if condition, and throw a unique error:

               throw new Error(
                `Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
              );

Finding a way to reproduce that would be fantastic, cause it's got me totally stumped. Check out no-test-callback if you're up for the challenge ;)

@SimenB
Copy link
Member

SimenB commented Aug 11, 2019

Do we wanna keep this open? I know #363 will close it, but maybe we can land this separately as well as we've been landing other parts of #363 already?

@G-Rath
Copy link
Collaborator Author

G-Rath commented Aug 11, 2019

@SimenB yeah this should be closed - we need parseExpectCall to land it 😬

@SimenB
Copy link
Member

SimenB commented Aug 12, 2019

🎉 This issue has been resolved in version 22.15.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@G-Rath G-Rath deleted the ts-migration/prefer-called-with branch August 13, 2019 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants