guideStore.spec.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import {ConfigFixture} from 'sentry-fixture/config';
  2. import {UserFixture} from 'sentry-fixture/user';
  3. import ConfigStore from 'sentry/stores/configStore';
  4. import GuideStore from 'sentry/stores/guideStore';
  5. import ModalStore from 'sentry/stores/modalStore';
  6. import {trackAnalytics} from 'sentry/utils/analytics';
  7. jest.mock('sentry/utils/analytics');
  8. describe('GuideStore', function () {
  9. let data!: Parameters<typeof GuideStore.fetchSucceeded>[0];
  10. beforeEach(function () {
  11. jest.clearAllMocks();
  12. ConfigStore.loadInitialData(
  13. ConfigFixture({
  14. user: UserFixture({
  15. id: '5',
  16. isSuperuser: false,
  17. dateJoined: '2020-01-01T00:00:00',
  18. }),
  19. })
  20. );
  21. GuideStore.init();
  22. data = [
  23. {
  24. guide: 'issue',
  25. seen: false,
  26. },
  27. {guide: 'issue_stream', seen: true},
  28. ];
  29. GuideStore.registerAnchor('issue_header_stats');
  30. GuideStore.registerAnchor('issue_sidebar_owners');
  31. GuideStore.registerAnchor('breadcrumbs');
  32. GuideStore.registerAnchor('issue_stream');
  33. });
  34. afterEach(() => {
  35. GuideStore.teardown();
  36. });
  37. it('should move through the steps in the guide', function () {
  38. GuideStore.fetchSucceeded(data);
  39. // Should pick the first non-seen guide in alphabetic order.
  40. expect(GuideStore.getState().currentStep).toEqual(0);
  41. expect(GuideStore.getState().currentGuide?.guide).toEqual('issue');
  42. // Should prune steps that don't have anchors.
  43. expect(GuideStore.getState().currentGuide?.steps).toHaveLength(3);
  44. GuideStore.nextStep();
  45. expect(GuideStore.getState().currentStep).toEqual(1);
  46. GuideStore.nextStep();
  47. expect(GuideStore.getState().currentStep).toEqual(2);
  48. GuideStore.closeGuide();
  49. expect(GuideStore.getState().currentGuide).toEqual(null);
  50. });
  51. it('should force show a guide with #assistant', function () {
  52. data = [
  53. {
  54. guide: 'issue',
  55. seen: true,
  56. },
  57. {guide: 'issue_stream', seen: false},
  58. ];
  59. GuideStore.fetchSucceeded(data);
  60. window.location.hash = '#assistant';
  61. window.dispatchEvent(new Event('load'));
  62. expect(GuideStore.getState().currentGuide?.guide).toEqual('issue');
  63. GuideStore.closeGuide();
  64. expect(GuideStore.getState().currentGuide?.guide).toEqual('issue_stream');
  65. window.location.hash = '';
  66. });
  67. it('should force hide', function () {
  68. expect(GuideStore.state.forceHide).toEqual(false);
  69. GuideStore.setForceHide(true);
  70. expect(GuideStore.state.forceHide).toEqual(true);
  71. GuideStore.setForceHide(false);
  72. expect(GuideStore.state.forceHide).toEqual(false);
  73. });
  74. it('should record analytics events when guide is cued', function () {
  75. const spy = jest.spyOn(GuideStore, 'recordCue');
  76. GuideStore.fetchSucceeded(data);
  77. expect(spy).toHaveBeenCalledWith('issue');
  78. expect(trackAnalytics).toHaveBeenCalledWith('assistant.guide_cued', {
  79. guide: 'issue',
  80. organization: null,
  81. });
  82. expect(spy).toHaveBeenCalledTimes(1);
  83. window.dispatchEvent(new Event('load'));
  84. expect(spy).toHaveBeenCalledTimes(1);
  85. GuideStore.nextStep();
  86. expect(spy).toHaveBeenCalledTimes(1);
  87. spy.mockRestore();
  88. });
  89. it('only shows guides with server data and content', function () {
  90. data = [
  91. {
  92. guide: 'issue',
  93. seen: true,
  94. },
  95. {
  96. guide: 'has_no_content',
  97. seen: false,
  98. },
  99. ];
  100. GuideStore.fetchSucceeded(data);
  101. expect(GuideStore.state.guides.length).toBe(1);
  102. expect(GuideStore.state.guides[0].guide).toBe(data[0].guide);
  103. });
  104. it('hides when a modal is open', function () {
  105. expect(GuideStore.getState().forceHide).toBe(false);
  106. ModalStore.openModal(() => <div />, {});
  107. expect(GuideStore.getState().forceHide).toBe(true);
  108. ModalStore.closeModal();
  109. expect(GuideStore.getState().forceHide).toBe(false);
  110. });
  111. it('should return a stable reference from getState', function () {
  112. ModalStore.openModal(() => <div />, {});
  113. const state = GuideStore.getState();
  114. expect(Object.is(state, GuideStore.getState())).toBe(true);
  115. });
  116. });