-
-
Notifications
You must be signed in to change notification settings - Fork 16
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
[RFC] enhancement(extension,repository): Add hidden __ident property to mocks and functions to differentiate them in conditional branching #313
base: master
Are you sure you want to change the base?
Conversation
a363ca0
to
ef93ab5
Compare
…fferentiate them in conditional typing
…ed methods as well
aba964b
to
acfffab
Compare
Hi, Do you mind explaining a bit more in details why this work is required? I am sure there is a reason for conditional typing, but I would like to explore a bit more if there are any other approaches. |
Just throwing my response on Slack here for reference:
|
Could we reuse the mock marker if we want to go in this direction? |
Thats a good point @Pmyl ! We could use that. I would first use this functionality only for pimitives types under a feature flag and then we need a define a solution that can work for other data types. |
I'm not sure I understand what you want to reuse the marker for. Do you mean storing the identity as the marker instead of the boolean value as it is right now? In that case, I suppose, we can even remove the emitted property definition and move that entirely to the proxy.
Right now, the marker instance is coupled with the extension module. If we are to wrap this at the |
Hi all :) i think we got different options here. Im sure we can find the best approach to identify when something its mock or not. We are definitely aware that this branch will not support all the scenario so in my opinion we should choose what to do next
In my opinion I would investigate more if its fisible to support all yhe possible types, then we can incrementally deliver one piece at the time. My worry about developing this as it is is that when we will discover how to do literals, interfaces this code will be obsolete. |
Sorry Martin about this. @Pmyl and I are happy to write down all the scenario and maybe help out to find the technical solution. We can open a document in the wiki where we try to identify all the implication of overload |
Hehe, I'm not gonna hate You :p A document sounds like a good idea. To fully support literals, we would have to adjust the emitted descriptor to proxy those as well. I tried to patch the proposed example above (martinjlowm@908af9c) and it results in the uncovered case of IIFE-emitted mocks ( I think the right way to go about this is to proxy everything through a factory and hash inputs based on type signature, so interfaces, classes, literals (that are not primitive) and even functions (anything that extends Object, really) can share the same factory - less code and smaller footprint 🎉 , the only problem is varying property names. I've been thinking about this for a couple of days, and I have yet to come up with a situation where it would be a problem. I suppose I can write a proof of concept. The only other way I see to work around this identifier is to implement all mocks as classes, so the prototype can be referenced. It's basically what the proxy does, without emitting a lot of extra code. |
Hi, yes, we should create a document where we explain the concern about this. This is the examples I'm not sure how you will identify correctly. function test(a: string, InterfaceA): boolean;
function test(a: number, InterfaceB): string; Let's say your are mocking |
I've given this some more thought and there are (as I see it) two directions we can go.
Pros:
Cons:
Pros:
Cons:
I'm starting to lean towards option 1 because it is fully backwards compatible and requires the least rewrite. That is assuming, the marker isn't intended for something else down the road. Option 2 has a lot of unknowns, but it really comes down to what the end goal for this project is... having a complex runtime vs. a complex transformer that emits (possibly) redundant code (as I see it as I'm writing this). It's not to say it's impossible to go down a different road later on. As for conditional branching, the following two PRs are really just depending on the decision that is made here. I would love your input, seeing as You brought the project to where it is today. :) edit: One thing I forgot, is how to handle option 1 with methods, they currently don't supply a marker. Perhaps we can merge the two somehow. The only issue there is that methods aren't to be instantiated like factories are. Or, perhaps we can bind the function, so we can reference edit 2: Binding
With new functions being created at the caller's perspective instead of here:
provideMethodWithDeferredValue and ends up returning something else than the specified function, e.g. a spy. I'm not sure if that will be a problem.
|
An interesting note about this is that if interfaces I think maybe that implies that anything you pass in which is assignable to
In addition to this, to limit the API of this framework, we can decide to only support mocked types, ones that have a marker, however, that would have to be a runtime check. I.e.:
with the mocked implementation of
Now, reusability, how do we accomplish this? We would need a way to check similarity of types and the proposal here: microsoft/TypeScript#9879 seems helpful - however, that is not implemented/exposed as of this writing, so we need some other way to do it. The first thing that comes to mind is to serialize the signatures and store them in a cache so they can be reused. Right now, the transformer decides what to register for a factory based on declarations through Now the serialization is not a simple thing to implement and it quickly becomes complex. Here are some practical examples:
I have a PoC right now for this that:
Right now, I am working on a first iteration of the serialization. What do you guys think? I hope I didn't miss anything crucial that this won't cover. |
Hi @martinjlowm, thanks for all these updates. I thought about it and I think we should find a better place to write down the proposal you are suggesting. I'm using Notion as a platform to document, comments proposal. If you share with me your email I'm happy to send you the link and we can start typing the proposal. I've already filled some of it with requirements @Pmyl I'll send you also the link. |
Differentiating mocked non-primitive function inputs is near impossible, especially if they are mocked through an IIFE-function. This PR adds a
__factory
__ident
property on non-primitive mocks using Proxy, so they can be differentiated when used in conditional typing.I'm open for ideas if this can be done any smarter. :) - It's similar to the Spy-identity property here: https://github.com/Typescript-TDD/ts-auto-mock/blob/master/test/frameworkContext/functions.test.ts