use-tutorial.spec.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import useTutorial from '@/shared/hooks/promotions/use-tutorial'
  2. import { useEffect, useState } from 'react'
  3. import {
  4. EditorProviders,
  5. makeTutorialProvider,
  6. } from '../../helpers/editor-providers'
  7. const TutorialTester = ({
  8. tutorial,
  9. failSilently,
  10. }: {
  11. tutorial: string
  12. failSilently?: boolean
  13. }) => {
  14. const {
  15. tryShowingPopup,
  16. dismissTutorial,
  17. checkCompletion,
  18. showPopup,
  19. completeTutorial,
  20. } = useTutorial(tutorial)
  21. const [error, setError] = useState(false)
  22. useEffect(() => {
  23. if (!checkCompletion()) {
  24. tryShowingPopup()
  25. }
  26. }, [checkCompletion, tryShowingPopup])
  27. if (error) {
  28. return <div>{tutorial} error</div>
  29. }
  30. if (!showPopup) {
  31. return null
  32. }
  33. return (
  34. <div>
  35. <p>{tutorial} active</p>
  36. <button onClick={() => dismissTutorial('promo-dismiss')}>Dismiss</button>
  37. <button
  38. onClick={() =>
  39. completeTutorial(
  40. { action: 'complete', event: 'promo-click' },
  41. { failSilently }
  42. ).catch(_ => {
  43. setError(true)
  44. })
  45. }
  46. >
  47. Complete
  48. </button>
  49. </div>
  50. )
  51. }
  52. describe('useTutorial', function () {
  53. beforeEach(function () {
  54. cy.intercept('POST', '/tutorial/test-tutorial/complete', {
  55. statusCode: 200,
  56. }).as('completeTutorial')
  57. })
  58. describe('with a tutorial that is not completed', function () {
  59. it('shows the popup', function () {
  60. cy.mount(
  61. <EditorProviders>
  62. <TutorialTester tutorial="test-tutorial" />
  63. </EditorProviders>
  64. )
  65. cy.findByText('test-tutorial active').should('be.visible')
  66. })
  67. it('dismisses the popup', function () {
  68. cy.mount(
  69. <EditorProviders>
  70. <TutorialTester tutorial="test-tutorial" />
  71. </EditorProviders>
  72. )
  73. cy.findByRole('button', { name: 'Dismiss' }).click()
  74. cy.findByText('test-tutorial active').should('not.exist')
  75. cy.wait('@completeTutorial')
  76. })
  77. it('completes the tutorial', function () {
  78. cy.mount(
  79. <EditorProviders>
  80. <TutorialTester tutorial="test-tutorial" />
  81. </EditorProviders>
  82. )
  83. cy.findByRole('button', { name: 'Complete' }).click()
  84. cy.findByText('test-tutorial active').should('not.exist')
  85. cy.wait('@completeTutorial')
  86. })
  87. })
  88. describe('with a tutorial that is already completed', function () {
  89. it('does not show the popup', function () {
  90. cy.mount(
  91. <EditorProviders
  92. providers={{
  93. TutorialProvider: makeTutorialProvider({
  94. inactiveTutorials: ['test-tutorial'],
  95. }),
  96. }}
  97. >
  98. <TutorialTester tutorial="test-tutorial" />
  99. </EditorProviders>
  100. )
  101. cy.findByText('test-tutorial active').should('not.exist')
  102. })
  103. })
  104. describe('with a tutorial that fails to complete', function () {
  105. it('fails silently by default', function () {
  106. cy.intercept('POST', '/tutorial/test-tutorial/complete', {
  107. statusCode: 500,
  108. }).as('completeTutorialFailure')
  109. cy.mount(
  110. <EditorProviders>
  111. <TutorialTester tutorial="test-tutorial" />
  112. </EditorProviders>
  113. )
  114. cy.findByRole('button', { name: 'Complete' }).click()
  115. cy.findByText('test-tutorial active').should('not.exist')
  116. cy.wait('@completeTutorialFailure')
  117. })
  118. it('throws an error if failSilently is set to false', function () {
  119. cy.intercept('POST', '/tutorial/test-tutorial/complete', {
  120. statusCode: 500,
  121. }).as('completeTutorialFailure')
  122. cy.mount(
  123. <EditorProviders>
  124. <TutorialTester tutorial="test-tutorial" failSilently={false} />
  125. </EditorProviders>
  126. )
  127. cy.findByRole('button', { name: 'Complete' }).click()
  128. cy.wait('@completeTutorialFailure')
  129. cy.findByText('test-tutorial error').should('be.visible')
  130. cy.findByText('test-tutorial active').should('not.exist')
  131. })
  132. })
  133. describe('for two tutorials at the same time', function () {
  134. // FIXME: This should work, but doesn't.
  135. // eslint-disable-next-line mocha/no-skipped-tests
  136. it.skip('only shows one popup at a time', function () {
  137. cy.mount(
  138. <EditorProviders>
  139. <TutorialTester tutorial="test-tutorial-1" />
  140. <TutorialTester tutorial="test-tutorial-2" />
  141. </EditorProviders>
  142. )
  143. cy.findAllByText(/active/).should('have.length', 1)
  144. })
  145. })
  146. })