[Enterprise Search] Telemetry: refactor to Kea logic file#81926
[Enterprise Search] Telemetry: refactor to Kea logic file#81926cee-chen merged 5 commits intoelastic:masterfrom
Conversation
There was a problem hiding this comment.
Just a check, could this test pass with a false positive in the case where this action never threw?
Like if someone updated the telemetry method to use post instead of put, I think this would still pass... because put is never called, the action never throws, and this catch is never executed. In that case, this test should fail but it would pass.
Just thinking that something written like the following might be more resilient:
it('throws an error if the telemetry endpoint fails', async () => {
const promise = Promise.reject()
mockHttpValues.http.put.get.mockReturnValue(promise);
let message = "";
TelemetryLogic.actions.sendTelemetry({ action: '', metric: '', product: '' });
try {
await promise;
} catch (e) {
message = e.message;
}
expect(message).toEqual('Unable to send telemetry');
});Actually, I'm wondering if this is already a false positive. As in, since this is not an async test method, is that catch ever even being triggered?
There was a problem hiding this comment.
Ohh super good point about false positives/this not being an async fn! 👍 I like your proposed solution a lot, will definitely implement it!
There was a problem hiding this comment.
You were super on point about it being a false positive! I added an expect.assertions(1) to the top of the test and confirmed that it had 0 assertions, which means the catch wasn't firing. Credit to this article for the nifty technique:
https://medium.com/@liran.tal/demystifying-jest-async-testing-patterns-b730d4cca4ec#a5c3
There was a problem hiding this comment.
Why do you add these here if you just end up importing telementry_logic.mock directly in all of the tests?
There was a problem hiding this comment.
Because that way you import a single __mocks__/kea.mock.ts to mock all possible shared logic file values/actions at once instead of having to manually and tediously mock every logic file that you need.
So for example, in product_card.test.tsx:
This file calls both KibanaLogic and TelemetryLogic. Because we have this shared kea.mock.ts helper, we only have to import it once and now the test file gracefully handles all instances of useValues and useActions, returning sane defaults that we can either spy on or override as needed (via our exported mock*Values/mock*Actions objs).
JasonStoltz
left a comment
There was a problem hiding this comment.
This looks great.
You're right, it seems to greatly simplify things. I had one hesitation about one of your unit tests, but other than that it looks great.
Thanks for doing this.
|
Also, I did not QA this. Let me know if that is something you'll need. |
- DRYs out need to import/pass http lib - adds product-specific helpers which DRYs out an extra line
- Create reusable mocks - Update overview_logic.ts to use new Kea mock helpers (required for recent_activity.test to pass)
+ update tests
1db25d7 to
41de835
Compare
41de835 to
589d65e
Compare
There was a problem hiding this comment.
I mentioned this in a comment in Slack, but repeating it here. I have this weird sense of guilt about this comment, like we're blaming Kea for doing something weird 😭
Actions are like events in Kea, and reducers and listeners are like event handlers.
I would not expect that triggering an event would return a value from an event handler. Therefore, I would not expect that dispatching an action would return a value from a listener.
I mean think about it, there could be multiple event listeners listening for that event, how would you even know which value to return from the action invocation if there are 5 different handlers or listeners running.
The same is true with Kea and Redux.
Kea abstracts some things away from Redux... like when you call an action in Kea, you are invoking it in a way that it appears like a direct invocation of the handler logic, and less like triggering an event:
sendTelemetry()
In Redux, it looks more like the following, which makes it less tempting to expect a return value:
store.dispatch({ type: 'sendTelemetry' })
This is basically a long winded way of saying if you shift your thinking a bit, this seems less like interference.
There was a problem hiding this comment.
Thanks for taking the time to write that all out Jason!!! Totally agreed and I found that super helpful / learned a few new things.
589d65e to
b1fb8eb
Compare
💚 Build SucceededMetrics [docs]@kbn/optimizer bundle module count
async chunks size
History
To update your PR or re-run it, just comment with: |
…82473) * Add new TelemetryLogic helpers - DRYs out need to import/pass http lib - adds product-specific helpers which DRYs out an extra line * Update all previous sendTelemetry fns to use new logic actions * Update unit tests for updated components - Create reusable mocks - Update overview_logic.ts to use new Kea mock helpers (required for recent_activity.test to pass) * Cleanup: Remove old sendTelemetry fn + update tests * [PR feedback] Correctly assert the async thrown error
Summary
This refactors our
sendTelemetry()utility function (that we primarily used for onClick actions) into a logic action, which allows us to not have to import/pass thehttpdependency in everysendTelemetrycall.Before:
After:
Hopefully the code speaks for itself and feels clearer / closer to the
<SendTelemetry />components. It also makes unit tests a little less verbose, as we have a lot more helpers in place for mocking Kea values/actions.Regression QA
All of the following telemetry actions/events should correctly send 200 XHR requests to
api/enterprise_search/stats:Checklist