userEventIntegration.ts 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import type {Hub} from '@sentry/types';
  2. import {fill, isThenable, loadModule} from '@sentry/utils';
  3. export function instrumentUserEvent(getCurrentHub: () => Hub): void {
  4. const pkg = loadModule('@testing-library/user-event') as any;
  5. ACTIONS.forEach((action: Action) => _patchAction(pkg.default, action, getCurrentHub));
  6. }
  7. type Action = (typeof ACTIONS)[number];
  8. const ACTIONS = [
  9. 'click',
  10. 'dblClick',
  11. 'type',
  12. 'clear',
  13. 'tab',
  14. 'hover',
  15. 'unhover',
  16. 'upload',
  17. 'selectOptions',
  18. 'deselectOptions',
  19. 'paste',
  20. 'keyboard',
  21. ];
  22. function _patchAction(userEvent: any, action: Action, getCurrentHub?: () => Hub): void {
  23. fill(userEvent, action, function (orig: () => void | Promise<unknown>) {
  24. return function patchedAction(this: unknown, ...args: unknown[]) {
  25. const scope = getCurrentHub?.().getScope();
  26. const parentSpan = scope?.getSpan();
  27. const span = parentSpan?.startChild({
  28. op: 'user event',
  29. description: action,
  30. });
  31. const maybePromise = orig.call(this, ...args);
  32. if (isThenable(maybePromise)) {
  33. return maybePromise.then((res: unknown) => {
  34. span?.end();
  35. return res;
  36. });
  37. }
  38. span?.end();
  39. return maybePromise;
  40. };
  41. });
  42. }