-
-
Notifications
You must be signed in to change notification settings - Fork 187
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
BREAKING Adds messenger to token controller #1166
Conversation
80cf8ad
to
33e207d
Compare
@@ -142,6 +142,7 @@ describe('TokenBalancesController', () => { | |||
onPreferencesStateChange: (listener) => preferences.subscribe(listener), | |||
onNetworkStateChange: (listener) => | |||
messenger.subscribe('NetworkController:stateChange', listener), | |||
messenger: undefined as any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance we could provide a real messenger object instead of nothing? We'd like to avoid using any
across the monorepo if we can, even in tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've created real messenger objects for those tests to avoid use of any.
Having said that, I don't think it's going to be scalable if we have to instantiate real dependencies instead of mocking them. If we are instantiating real TokensController
with real messengers for other controllers, these are no longer unit tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a compromise where we can still provide a mock for these arguments to reduce coupling, but cast to the correct type rather than any
, so a as unknown as TokensControllerMessenger
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed another commit with the as unknown as TokensControllerMessenger
. The messenger is not even used during those tests, so it's set to undefined
.
We should not have to use real object instantiations on unit tests when that is not the subject of the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean, but I'm not so sure that using a real messenger would make this an integration test. Unless we're using it to talk to another controller — that would be unnecessary. But if we're just using it to satisfy the argument, then I don't see why we can't use a real one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd argue it's just a matter of future-proofing and minimising the code being executed in the test for the sake of avoiding fragility and ensuring we're testing a isolated unit whenever possible, rather than dependency code, in this case the ControllerMessenger
.
As an example, if we were to change the code in future to invoke a method in the TokensController
from the TokenBalancesController
that did use the messenger, any related errors in the messenger code would needlessly cause the TokenBalancesController
tests to fail and they would be harder to diagnose as the errors would be originating from code the test wasn't intending to validate.
There's also a performance argument with this pattern if we're consistently loading additional dependencies and code that isn't functionally required for a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change seems fine to me as a short-term fix because the tests shouldn't have a TokenController
in the fist place, but fixing that would be out-of-scope of this PR.
But in general I would recommend using a real controller messenger in tests, if only because it's such a simple construct that mocking it would add complexity. The messenger is meant as a way of doing dependency injection, it's a way for us to pass mocks into the code under test.
It's the use of additional controllers that aren't under test that makes this example needlessly complex. Not the messenger. In your example here @matthewwalsh0 you seem to be talking about one such case. I don't think @mcmire meant to suggest that using real controllers that aren't under-test is a good idea.
33e207d
to
0c0e8bf
Compare
packages/assets-controllers/src/TokenBalancesController.test.ts
Outdated
Show resolved
Hide resolved
2c4f33f
to
8a1d2b9
Compare
1effe0f
to
bd297cc
Compare
|
||
this._acceptApproval(suggestedAssetID); | ||
|
||
const acceptedSuggestedAssetMeta = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to remove the line that updates status directly (suggestedAssetMeta.status = SuggestedAssetStatus.accepted;
) and replace it by a new object using the spread operator, as otherwise that line throws a read error when using this controller in mobile codebase with react-native.
Attempted to assign to readonly property
const rejectedSuggestedAssetMeta = { | ||
...suggestedAssetMeta, | ||
status: SuggestedAssetStatus.rejected, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with the previous one, I had to create a new object instead of updating status directly to prevent an error in react-native codebase.
id: suggestedAssetMeta.id, | ||
origin: ORIGIN_METAMASK, | ||
type: APPROVAL_TYPE, | ||
requestData: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For mobile, we will need requestData to be populated with the following values, as it currently relies on the suggestedAssetMeta
object sent by the pendingSuggestedAsset
event.
Unfortunately, the type SuggestedAssetMeta
is not compatible with requestData
as it has several optional and an unknown field within the Token
type, so we are sending precisely the data it needs.
101114c
to
b0ff768
Compare
77afb2f
* BREAKING - add messenger to token controller * trigger confirmation via approval controller * unit tests
* BREAKING - add messenger to token controller * trigger confirmation via approval controller * unit tests
BREAKING Adds messenger to token controller
Description
Adds a messenger to
TokensController
so that the confirmation can be triggered by sending a message toApprovalController
.BREAKING:
CHANGED:
ApprovalController
messages to initiate and complete the request instead of an event.Checklist
Issue
Resolves https://github.com/MetaMask/MetaMask-planning/issues/409