guideStore.spec.jsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import React from 'react';
  2. import GuideStore from 'app/stores/guideStore';
  3. import GuideAnchor from 'app/components/assistant/guideAnchor';
  4. import ConfigStore from 'app/stores/configStore';
  5. describe('GuideStore', function() {
  6. let sandbox;
  7. let anchor1 = <GuideAnchor target="target 1" type="text" />;
  8. let anchor2 = <GuideAnchor target="target 2" type="text" />;
  9. let data;
  10. ConfigStore.config = {
  11. user: {
  12. isSuperuser: true,
  13. },
  14. };
  15. beforeEach(function() {
  16. GuideStore.init();
  17. sandbox = sinon.sandbox.create();
  18. data = {
  19. Guide1: {
  20. cue: 'Click here for a tour of the issue page',
  21. id: 1,
  22. required_targets: ['target 1'],
  23. steps: [
  24. {message: 'Message 1', target: 'target 1', title: '1. Title 1'},
  25. {message: 'Message 2', target: 'target 2', title: '2. Title 2'},
  26. {message: 'Message 3', target: 'target 3', title: '3. Title 3'},
  27. ],
  28. seen: true,
  29. },
  30. Guide2: {
  31. cue: 'Some other guide here',
  32. id: 2,
  33. required_targets: ['target 1'],
  34. steps: [
  35. {message: 'Message 1', target: 'target 1', title: '1. Title 1'},
  36. {message: 'Message 2', target: 'target 2', title: '2. Title 2'},
  37. ],
  38. seen: false,
  39. },
  40. alert_reminder_1: {
  41. id: 3,
  42. guide_type: 'tip',
  43. required_targets: ['target 1'],
  44. steps: [{message: 'Message 1', target: 'target 1', title: '1. Title 1'}],
  45. seen: false,
  46. },
  47. };
  48. GuideStore.onRegisterAnchor(anchor1);
  49. GuideStore.onRegisterAnchor(anchor2);
  50. MockApiClient.addMockResponse({
  51. url: '/projects/org/proj/stats/',
  52. body: [[1, 500], [2, 300], [3, 500]],
  53. });
  54. MockApiClient.addMockResponse({
  55. url: '/projects/org/proj/rules/',
  56. body: [],
  57. });
  58. });
  59. afterEach(function() {
  60. sandbox.restore();
  61. });
  62. it('should move through the steps in the guide', function() {
  63. GuideStore.onFetchSucceeded(data);
  64. let guide = GuideStore.state.currentGuide;
  65. // Should pick the first non-seen guide in alphabetic order.
  66. expect(guide.id).toEqual(2);
  67. expect(guide.steps).toHaveLength(2);
  68. GuideStore.onNextStep();
  69. expect(GuideStore.state.currentStep).toEqual(1);
  70. GuideStore.onCloseGuide();
  71. guide = GuideStore.state.currentGuide;
  72. // We don't have the alert reminder guide's data yet, so we can't show it.
  73. expect(guide).toEqual(null);
  74. });
  75. it('should force show a guide', function() {
  76. GuideStore.onFetchSucceeded(data);
  77. window.location.hash = '#assistant';
  78. window.dispatchEvent(new Event('hashchange'));
  79. expect(GuideStore.state.currentGuide.id).toEqual(1);
  80. // Should prune steps that don't have anchors.
  81. expect(GuideStore.state.currentGuide.steps).toHaveLength(2);
  82. GuideStore.onCloseGuide();
  83. expect(GuideStore.state.currentGuide.id).toEqual(2);
  84. window.location.hash = '';
  85. });
  86. it('should render tip', async function() {
  87. data.Guide2.seen = true;
  88. GuideStore.onFetchSucceeded(data);
  89. expect(GuideStore.state.currentGuide).toEqual(null);
  90. let spy = jest.spyOn(GuideStore, 'isDefaultAlert').mockImplementation(() => true);
  91. GuideStore.onSetActiveOrganization({id: 1, slug: 'org'});
  92. GuideStore.onSetActiveProject({id: 1, slug: 'proj'});
  93. await tick();
  94. expect(GuideStore.state.currentGuide.id).toEqual(3);
  95. spy.mockRestore();
  96. });
  97. it('should record analytics events when guide is cued', function() {
  98. let spy = jest.spyOn(GuideStore, 'recordCue');
  99. GuideStore.onFetchSucceeded(data);
  100. expect(spy).toHaveBeenCalledWith(data.Guide2.id, data.Guide2.cue);
  101. expect(spy).toHaveBeenCalledTimes(1);
  102. spy.mockRestore();
  103. });
  104. it('should not send multiple cue analytics events for same guide', function() {
  105. let spy = jest.spyOn(GuideStore, 'recordCue');
  106. GuideStore.onFetchSucceeded(data);
  107. expect(spy).toHaveBeenCalledWith(data.Guide2.id, data.Guide2.cue);
  108. expect(spy).toHaveBeenCalledTimes(1);
  109. GuideStore.updateCurrentGuide();
  110. expect(spy).toHaveBeenCalledTimes(1);
  111. spy.mockRestore();
  112. });
  113. });