mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
[web] Ensure only one tutorial shows at once GitOrigin-RevId: 797c677a3d45635451485d79ed1c0705819ed5ad
187 lines
5.2 KiB
TypeScript
187 lines
5.2 KiB
TypeScript
import useTutorial from '@/shared/hooks/promotions/use-tutorial'
|
|
import { useEffect, useState } from 'react'
|
|
import { EditorProviders } from '../../helpers/editor-providers'
|
|
import { makeTutorialProvider } from '../../helpers/make-tutorial-provider'
|
|
|
|
const TutorialTester = ({
|
|
tutorial,
|
|
failSilently,
|
|
}: {
|
|
tutorial: string
|
|
failSilently?: boolean
|
|
}) => {
|
|
const {
|
|
tryShowingPopup,
|
|
dismissTutorial,
|
|
checkCompletion,
|
|
showPopup,
|
|
completeTutorial,
|
|
} = useTutorial(tutorial)
|
|
const [error, setError] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (!checkCompletion()) {
|
|
tryShowingPopup()
|
|
}
|
|
}, [checkCompletion, tryShowingPopup])
|
|
|
|
if (error) {
|
|
return <div>{tutorial} error</div>
|
|
}
|
|
|
|
if (!showPopup) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<p>{tutorial} active</p>
|
|
<button onClick={() => dismissTutorial('promo-dismiss')}>Dismiss</button>
|
|
<button
|
|
onClick={() =>
|
|
completeTutorial(
|
|
{ action: 'complete', event: 'promo-click' },
|
|
{ failSilently }
|
|
).catch(_ => {
|
|
setError(true)
|
|
})
|
|
}
|
|
>
|
|
Complete
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
describe('useTutorial', function () {
|
|
beforeEach(function () {
|
|
cy.intercept('POST', '/tutorial/test-tutorial/complete', {
|
|
statusCode: 200,
|
|
}).as('completeTutorial')
|
|
})
|
|
|
|
describe('with a tutorial that is not completed', function () {
|
|
it('shows the popup', function () {
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial" />
|
|
</EditorProviders>
|
|
)
|
|
|
|
cy.findByText('test-tutorial active').should('be.visible')
|
|
})
|
|
|
|
it('dismisses the popup', function () {
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial" />
|
|
</EditorProviders>
|
|
)
|
|
cy.findByRole('button', { name: 'Dismiss' }).click()
|
|
cy.findByText('test-tutorial active').should('not.exist')
|
|
cy.wait('@completeTutorial')
|
|
})
|
|
|
|
it('completes the tutorial', function () {
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial" />
|
|
</EditorProviders>
|
|
)
|
|
cy.findByRole('button', { name: 'Complete' }).click()
|
|
cy.findByText('test-tutorial active').should('not.exist')
|
|
cy.wait('@completeTutorial')
|
|
})
|
|
})
|
|
|
|
describe('with a tutorial that is already completed', function () {
|
|
it('does not show the popup', function () {
|
|
cy.mount(
|
|
<EditorProviders
|
|
providers={{
|
|
TutorialProvider: makeTutorialProvider({
|
|
inactiveTutorials: ['test-tutorial'],
|
|
}),
|
|
}}
|
|
>
|
|
<TutorialTester tutorial="test-tutorial" />
|
|
</EditorProviders>
|
|
)
|
|
cy.findByText('test-tutorial active').should('not.exist')
|
|
})
|
|
})
|
|
|
|
describe('with a tutorial that fails to complete', function () {
|
|
it('fails silently by default', function () {
|
|
cy.intercept('POST', '/tutorial/test-tutorial/complete', {
|
|
statusCode: 500,
|
|
}).as('completeTutorialFailure')
|
|
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial" />
|
|
</EditorProviders>
|
|
)
|
|
cy.findByRole('button', { name: 'Complete' }).click()
|
|
cy.findByText('test-tutorial active').should('not.exist')
|
|
cy.wait('@completeTutorialFailure')
|
|
})
|
|
|
|
it('throws an error if failSilently is set to false', function () {
|
|
cy.intercept('POST', '/tutorial/test-tutorial/complete', {
|
|
statusCode: 500,
|
|
}).as('completeTutorialFailure')
|
|
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial" failSilently={false} />
|
|
</EditorProviders>
|
|
)
|
|
cy.findByRole('button', { name: 'Complete' }).click()
|
|
cy.wait('@completeTutorialFailure')
|
|
cy.findByText('test-tutorial error').should('be.visible')
|
|
cy.findByText('test-tutorial active').should('not.exist')
|
|
})
|
|
})
|
|
|
|
describe('for two tutorials at the same time', function () {
|
|
beforeEach(function () {
|
|
cy.intercept('POST', '/tutorial/test-tutorial-1/complete', {
|
|
statusCode: 200,
|
|
}).as('completeTutorial1')
|
|
cy.intercept('POST', '/tutorial/test-tutorial-2/complete', {
|
|
statusCode: 200,
|
|
}).as('completeTutorial2')
|
|
})
|
|
|
|
it('only shows one popup at a time', function () {
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial-1" />
|
|
<TutorialTester tutorial="test-tutorial-2" />
|
|
</EditorProviders>
|
|
)
|
|
|
|
cy.findAllByText(/active/).should('have.length', 1)
|
|
})
|
|
|
|
it('shows the second popup after the first is completed', function () {
|
|
cy.mount(
|
|
<EditorProviders>
|
|
<TutorialTester tutorial="test-tutorial-1" />
|
|
<TutorialTester tutorial="test-tutorial-2" />
|
|
</EditorProviders>
|
|
)
|
|
|
|
cy.findByText('test-tutorial-1 active').should('be.visible')
|
|
cy.findByText('test-tutorial-2 active').should('not.exist')
|
|
|
|
cy.findByRole('button', { name: 'Complete' }).click()
|
|
cy.wait('@completeTutorial1')
|
|
|
|
cy.findByText('test-tutorial-1 active').should('not.exist')
|
|
cy.findByText('test-tutorial-2 active').should('be.visible')
|
|
})
|
|
})
|
|
})
|