Conversation
There was a problem hiding this comment.
As mentioned, currently I'm just logging these cases. Also lmk if there are other ways to log these messages.
There was a problem hiding this comment.
Since this is inside a static function, we could pass this as a parameter to the function, but considering that's a public API, I preferred to leave it like this... It also looks like we don't have tests for this function as of yet so something to think about.
I perform the validation as early as possible, after some other validations
There was a problem hiding this comment.
🤔 we don't have a visibleForTesting alternative of the configure, but we do have one for the initializer.
Maybe we could have the apiKeyValidator as a property of Purchases and pass it into the initializer?
There was a problem hiding this comment.
It also looks like we don't have tests for this function as of yet so something to think about
Filed as https://revenuecats.atlassian.net/browse/CSDK-101, let's take care of it once this PR gets merged!
There was a problem hiding this comment.
This could be abstracted to a @Before block... I just wasn't sure about adding one just for this. We could also use parameterized tests for these tests, but I don't like them as much since you lose the custom test name (and not sure if they are available in JUnit4..)
There was a problem hiding this comment.
I think you just volunteered to upgrade to JUnit 5 😈
There was a problem hiding this comment.
I think you just volunteered to upgrade to JUnit 5 😈
There was a problem hiding this comment.
🤔 we don't have a visibleForTesting alternative of the configure, but we do have one for the initializer.
Maybe we could have the apiKeyValidator as a property of Purchases and pass it into the initializer?
There was a problem hiding this comment.
It also looks like we don't have tests for this function as of yet so something to think about
Filed as https://revenuecats.atlassian.net/browse/CSDK-101, let's take care of it once this PR gets merged!
|
Looking great @tonidero! I left a few comments regarding testing, and we should update the prefix |
There was a problem hiding this comment.
The API key wasn't exposed to the Purchases object itself. I thought about passing it to the constructor of the APIKeyValidator so we wouldn't need to pass it to Purchases, but it felt like that was a function parameter and not a class property. Lmk if you think otherwise
There was a problem hiding this comment.
I wonder if this is a smell. Maybe it means that the validation should be outside by the configure method like in iOS? Then you wouldn't need to inject these 2 things in here.
There was a problem hiding this comment.
Right, on a first iteration I had it there. However, the configure method is not currently tested in Android, which would leave a gap on our test to make sure that the validation actually happened. After discussing with Andy, he suggested moving the validation to the purchases constructor, which would allow for easier testing than on the configure method.
Having said that, I agree it's not ideal having to add 2 extra parameters only for this and we have already created a task to add tests for the configure method (https://revenuecats.atlassian.net/browse/CSDK-101). So we could potentially move this back there after those tests have been added. I'm working on this task today, so we can hold this to after that's done
There was a problem hiding this comment.
Did the refactor for the configure method in #543 and made this PR point to that one. Lmk what you think!
There was a problem hiding this comment.
In all honesty, I copied the message from iOS, but yeah, it improves readability I would say 👍
There was a problem hiding this comment.
I need to double check something with you... If we don't make this class internal, is it accessible for devs? I don't think so right? They would have to do implementation on the common library, or we would have to be doing api on common from the purchases module, right?
Sorry I am asking this but I always get confused haha
There was a problem hiding this comment.
No worries! And that's correct, devs shouldn't have access to this class since purchases uses implementation on common. Devs shouldn't have access to it unless we used api instead of implementation on the purchases module.
| "configure the SDK to use Google.\nSee https://rev.cat/auth for more details." | ||
| const val INVALID_API_KEY = "The specified API Key is not recognized.\n" + | ||
| "Ensure that you are using the public app-specific API key, " + | ||
| " which should look like 'goog_1a2b3c4d5e6f7h' or 'amzn_1a2b3c4d5e6f7h'.\n" + |
There was a problem hiding this comment.
It looks like we have a double space here - one after the comma, one before the next line
There was a problem hiding this comment.
Good eye! @NachoSoto I copied this message from iOS, so we probably would need to fix this there as well.
NachoSoto
left a comment
There was a problem hiding this comment.
Much cleaner! I love it.
|
|
||
| require(context.applicationContext is Application) { "Needs an application context." } | ||
|
|
||
| apiKeyValidator.validateAndLog(apiKey, store) |
| OTHER_PLATFORM | ||
| } | ||
|
|
||
| @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) |
There was a problem hiding this comment.
This annotation is really useful since it gives you warnings if you try to go against the marked visibility. Though I think we should avoid using it as much as possible, since I believe we should test classes only with their public API. In this case, since the side effects of the public API are only logging, this was much easier though.
| private const val GOOGLE_API_KEY_PREFIX = "goog_" | ||
| private const val AMAZON_API_KEY_PREFIX = "amzn_" |
There was a problem hiding this comment.
Can these be namespaced inside of APIKeyValidator? Not sure if that's the Kotlin thing to do though.
There was a problem hiding this comment.
So in order to make this a compile time constant, the options are to declare it as a top level constant (like this) or in a companion object inside the class. Both would work, but the companion object approach is slightly dirtier IMO.
If we had to make a public compile time constant and tie it to the class, then using a companion object would be the way to go but for
a private one I prefer this approach. Don't know of any best practices about this though, but this answer thinks the same way I do https://stackoverflow.com/a/49977253
Description
Android part of https://revenuecats.atlassian.net/browse/CSDK-57
With this change we log a series of situations:
This behavior was tested using unit tests and manually through the
purchase-testerappTODO
Note that this is based on #543