From a100cb5502ee5711f790f0bd4a4b5ec3c589c763 Mon Sep 17 00:00:00 2001 From: Esen Date: Sun, 12 Jan 2025 14:49:42 +0600 Subject: [PATCH] cleanup --- src/components/Tutorial/__tests__/Tutorial.ts | 430 ++++++++---------- src/test-helpers/createTestApp.tsx | 15 +- 2 files changed, 192 insertions(+), 253 deletions(-) diff --git a/src/components/Tutorial/__tests__/Tutorial.ts b/src/components/Tutorial/__tests__/Tutorial.ts index 14eac52e44..ae5839f441 100644 --- a/src/components/Tutorial/__tests__/Tutorial.ts +++ b/src/components/Tutorial/__tests__/Tutorial.ts @@ -1,140 +1,145 @@ import { getByText, screen } from '@testing-library/dom' import userEvent from '@testing-library/user-event' import { act } from 'react' -import { importTextActionCreator as importText } from '../../../actions/importText' -import { newThoughtActionCreator as newThought } from '../../../actions/newThought' import { HOME_TOKEN, TUTORIAL2_STEP_CHOOSE, + TUTORIAL2_STEP_CONTEXT1, + TUTORIAL2_STEP_CONTEXT1_PARENT, + TUTORIAL2_STEP_CONTEXT1_SUBTHOUGHT, + TUTORIAL2_STEP_CONTEXT2_PARENT, + TUTORIAL2_STEP_CONTEXT_VIEW_EXAMPLES, + TUTORIAL2_STEP_CONTEXT_VIEW_OPEN, + TUTORIAL2_STEP_CONTEXT_VIEW_SELECT, + TUTORIAL2_STEP_START, TUTORIAL_STEP_AUTOEXPAND, + TUTORIAL_STEP_AUTOEXPAND_EXPAND, + TUTORIAL_STEP_FIRSTTHOUGHT, TUTORIAL_STEP_FIRSTTHOUGHT_ENTER, TUTORIAL_STEP_SECONDTHOUGHT, + TUTORIAL_STEP_SECONDTHOUGHT_ENTER, + TUTORIAL_STEP_START, TUTORIAL_STEP_SUBTHOUGHT, + TUTORIAL_STEP_SUBTHOUGHT_ENTER, TUTORIAL_STEP_SUCCESS, } from '../../../constants' import exportContext from '../../../selectors/exportContext' import store from '../../../stores/app' -import createTestApp, { cleanupTestApp, createTestAppWithTutorial } from '../../../test-helpers/createTestApp' -import dispatch from '../../../test-helpers/dispatch' -import { setCursorFirstMatchActionCreator as setCursorFirstMatch } from '../../../test-helpers/setCursorFirstMatch' +import createTestApp, { cleanupTestApp, cleanupTestEventHandlers } from '../../../test-helpers/createTestApp' // as per https://testing-library.com/docs/user-event/options/#advancetimers // we should avoid using { delay: null }, and use jest.advanceTimersByTime instead const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }) -describe.skip('Tutorial test keyboard events', () => { - beforeEach(createTestApp) - afterEach(cleanupTestApp) - it('2 enters', async () => { - await user.keyboard('{Enter}') - await user.keyboard('{Enter}') - }) +/** Get last created thought in the document, used mostly after `user.keyboard('{Enter}')`. */ +const lastThought = () => Array.from(document.querySelectorAll('[contenteditable="true"]')).at(-1)! - it('another 2 enters', async () => { - await user.keyboard('{Enter}') - await user.keyboard('{Enter}') - }) - - it('final 2 enters', async () => { - await user.keyboard('{Enter}') - await user.keyboard('{Enter}') - - const exported = exportContext(store.getState(), [HOME_TOKEN], 'text/plain') - console.log(exported) - }) - - afterAll(() => { - const exported = exportContext(store.getState(), [HOME_TOKEN], 'text/plain') - console.log(exported) - }) -}) +/** Ensure we are at the given step of the tutorial. */ +const ensureStep = (step: number) => { + expect(store.getState().storageCache?.tutorialStep).toBe(step) +} describe('Tutorial 1', async () => { - beforeEach(createTestAppWithTutorial) + beforeEach(() => createTestApp({ tutorial: true })) + afterEach(cleanupTestEventHandlers) afterAll(cleanupTestApp) describe('step start', () => { it('shows the welcome text', () => { + ensureStep(TUTORIAL_STEP_START) expect(screen.getByText('Welcome to your personal thoughtspace.')).toBeInTheDocument() }) it('shows the "Next" button, that leads to the first step', async () => { await user.click(screen.getByText('Next')) - expect( - screen.getByText('First, let me show you how to create a new thought', { exact: false }), - ).toBeInTheDocument() + expect(screen.getByText(/First, let me show you how to create a new thought/)).toBeInTheDocument() }) }) it('step first thought - how to create a thought ', async () => { + ensureStep(TUTORIAL_STEP_FIRSTTHOUGHT) expect(screen.getByText('Hit the Enter key to create a new thought.')).toBeInTheDocument() - - await act(() => user.keyboard('{Enter}')) + await user.keyboard('{Enter}') expect(screen.getByText('You did it!')).toBeInTheDocument() - expect(screen.getByText('Now type something. Anything will do.')).toBeInTheDocument() - await dispatch(newThought({ value: 'my first thought' })) + ensureStep(TUTORIAL_STEP_FIRSTTHOUGHT_ENTER) + expect(screen.getByText('Now type something. Anything will do.')).toBeInTheDocument() + await user.type(lastThought(), 'my first thought') + await user.keyboard('{Enter}') await act(vi.runOnlyPendingTimersAsync) - expect(screen.getByText('Click the Next button when you are ready to continue.')).toBeInTheDocument() - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL_STEP_FIRSTTHOUGHT_ENTER) }) it('step second thought - prompts to add another thought', async () => { - await dispatch(newThought({ value: 'a thought' })) - await act(vi.runOnlyPendingTimersAsync) - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL_STEP_SECONDTHOUGHT) + expect(screen.getByText('Well done!')).toBeInTheDocument() + expect(screen.getByText(/Try adding another thought/)).toBeInTheDocument() + ensureStep(TUTORIAL_STEP_SECONDTHOUGHT) - expect(screen.getByText('Try adding another thought. Do you remember how to do it?')).toBeInTheDocument() - await dispatch(newThought({ value: 'a new thought' })) + await user.type(lastThought(), 'my second thought') + await user.keyboard('{Enter}') await act(vi.runOnlyPendingTimersAsync) + + ensureStep(TUTORIAL_STEP_SECONDTHOUGHT_ENTER) + expect(screen.getByText('Good work!')).toBeInTheDocument() + expect(screen.getByText('Now type some text for the new thought.')).toBeInTheDocument() + await user.type(lastThought(), 'third thought') + await user.keyboard('{Enter}') + await act(vi.runOnlyPendingTimersAsync) }) it('step subthought - how to create a thought inside thought', async () => { - await user.click(screen.getByText('Next')) - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL_STEP_SUBTHOUGHT) - await dispatch([ - newThought({ value: 'uncle' }), - newThought({ - value: 'parent', - }), - newThought({ - value: 'child', - insertNewSubthought: true, - }), - ]) + ensureStep(TUTORIAL_STEP_SUBTHOUGHT) + expect(exportContext(store.getState(), [HOME_TOKEN], 'text/plain')).toBe( + `- __ROOT__ + - my first thought + - my second thought + - third thought + - `, + ) + + // Now I am going to show you how to add a thought within another thought. + expect(screen.getByText(/Now I am going to show you how to add a thought/)).toBeInTheDocument() + + // since we have cursor on empty thought + expect(screen.getByText(/Hit the Delete key to delete the current blank thought/)).toBeInTheDocument() + expect(screen.getByText(/Then hold the Ctrl key and hit the Enter key/)).toBeInTheDocument() + await user.keyboard('{Backspace}') + await user.keyboard('{Control>}{Enter}{/Control}') await act(vi.runOnlyPendingTimersAsync) - expect(screen.getByText(`As you can see, the new thought "child" is nested`, { exact: false })).toBeInTheDocument() - expect(getByText(screen.getByTestId('tutorial-step'), 'parent', { exact: false })).toBeInTheDocument() + await user.type(lastThought(), 'child') + await act(vi.runOnlyPendingTimersAsync) + expect(exportContext(store.getState(), [HOME_TOKEN], 'text/plain')).toBe( + `- __ROOT__ + - my first thought + - my second thought + - third thought + - child`, + ) + // as you can see, the new thought "child" is nested within "third thought" + expect(screen.getByText(/As you can see, the new thought "child" is nested/)).toBeInTheDocument() + expect(getByText(screen.getByTestId('tutorial-step'), /"third thought"/)).toBeInTheDocument() + + ensureStep(TUTORIAL_STEP_SUBTHOUGHT_ENTER) + await user.click(screen.getByText('Next')) }) - describe('step autoexpand - shows that thoughts expand and collapse on outside click', async () => { - it('tells us about thoughts being hidden when clicked away', async () => { - await user.click(screen.getByText('Next')) - - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL_STEP_AUTOEXPAND) - expect( - screen.getByText('thoughts are automatically hidden when you click away', { exact: false }), - ).toBeInTheDocument() + describe('step autoexpand', async () => { + it('thoughts are automatically hidden when you click away', async () => { + ensureStep(TUTORIAL_STEP_AUTOEXPAND) + expect(screen.getByText(/thoughts are automatically hidden when you click away/)).toBeInTheDocument() }) - it('tells us to click on uncle to hide the child', async () => { - await dispatch([ - importText({ - text: ` - - parent - - child - - uncle - `, - }), - ]) - await act(() => user.click(screen.getByText('uncle'))) + it('click on "uncle" thought to hide child', async () => { + await user.click(screen.getByText('my second thought')) expect(screen.getByText('Notice that "child" is hidden now.', { exact: false })).toBeInTheDocument() + ensureStep(TUTORIAL_STEP_AUTOEXPAND_EXPAND) }) - it('tells us to click on the parent to reveal the child', async () => { - await act(() => user.click(Array.from(screen.getAllByText('parent')).at(-1)!)) + it('click back on a "parent" thought to reveal child', async () => { + expect(screen.getByText(/Click "third thought" to reveal its subthought "child"/)).toBeInTheDocument() + await user.click(screen.getAllByText('third thought').at(-1)!) expect(screen.getByText('Lovely. You have completed the tutorial', { exact: false })).toBeInTheDocument() + ensureStep(TUTORIAL_STEP_SUCCESS) }) }) @@ -147,216 +152,145 @@ describe('Tutorial 1', async () => { expect(screen.getByText('Play on my own')).toBeInTheDocument() expect(screen.getByText('Learn more')).toBeInTheDocument() }) - - it.skip('hides tutorial after clicking "Play on my own"', async () => { - await user.click(screen.getByText('Play on my own')) - expect(() => screen.getByTestId('tutorial-step')).toThrow('Unable to find an element') - }) }) }) describe('Tutorial 2', async () => { - describe('step start - tell about context menu', async () => { - it('tell about context menu', async () => { - await cleanupTestApp() - await createTestAppWithTutorial() - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL_STEP_SUCCESS) - - await user.click(screen.getByText('Learn more')) - - expect( - screen.getByText(`If the same thought appears in more than one place`, { exact: false }), - ).toBeInTheDocument() - expect( - screen.getByText(`shows a small number to the right of the thought, for example`, { exact: false }), - ).toBeInTheDocument() - }) + beforeEach(() => createTestApp({ tutorial: true })) + afterEach(cleanupTestEventHandlers) + afterAll(cleanupTestApp) + it('step start - tell about context menu', async () => { + await user.click(screen.getByText('Learn more')) + + ensureStep(TUTORIAL2_STEP_START) + expect(screen.getByText(`If the same thought appears in more than one place`, { exact: false })).toBeInTheDocument() + expect( + screen.getByText(`shows a small number to the right of the thought, for example`, { exact: false }), + ).toBeInTheDocument() }) - describe('step choose', async () => { - beforeEach(createTestAppWithTutorial) - it('gives 3 choices of what project to proceed with', async () => { - await user.click(screen.getByText('Next')) - expect( - screen.getByText('For this tutorial, choose what kind of content you want to create', { exact: false }), - ).toBeInTheDocument() - expect(screen.getByText('To-Do List')).toBeInTheDocument() - expect(screen.getByText('Journal Theme')).toBeInTheDocument() - expect(screen.getByText('Book/Podcast Notes')).toBeInTheDocument() - }) + it('step choose - gives 3 choices of what project to proceed with', async () => { + await user.click(screen.getByText('Next')) + ensureStep(TUTORIAL2_STEP_CHOOSE) + expect(screen.getByText(/For this tutorial, choose what kind of content you want to create/)).toBeInTheDocument() + expect(screen.getByText('To-Do List')).toBeInTheDocument() + expect(screen.getByText('Journal Theme')).toBeInTheDocument() + expect(screen.getByText('Book/Podcast Notes')).toBeInTheDocument() }) - describe('step context 1 parent, prompt for creating a first todo', async () => { - beforeEach(createTestAppWithTutorial) - - it('step context 1 parent, prompt for creating a first todo', async () => { - console.log(store.getState().storageCache?.tutorialStep) - expect(store.getState().storageCache?.tutorialStep).toBe(TUTORIAL2_STEP_CHOOSE) - await user.click(screen.getAllByText('To-Do List').at(-1)!) - await act(vi.runOnlyPendingTimersAsync) - - expect( - screen.getByText('Excellent choice. Now create a new thought with the text “Home”', { exact: false }), - ).toBeInTheDocument() - await act(vi.runOnlyPendingTimersAsync) - - await user.keyboard('{Enter}') - await user.type(document.querySelector('[contenteditable="true"]') as HTMLElement, 'Home', { - skipAutoClose: true, - }) - // await user.keyboard('{Enter}') - await act(vi.runOnlyPendingTimersAsync) + it('step context 1 parent - we create "Home" thought with children', async () => { + await user.click(screen.getAllByText('To-Do List').at(-1)!) + expect(screen.getByText(/Excellent choice. Now create a new thought with the text “Home”/)).toBeInTheDocument() + ensureStep(TUTORIAL2_STEP_CONTEXT1_PARENT) - expect(screen.getByText(/Let's say that you want to make a list of things/)).toBeInTheDocument() - expect(screen.getByText(/Add a thought with the text "To Do"/)).toBeInTheDocument() - - await act(vi.runOnlyPendingTimersAsync) - await user.keyboard('{Control>}{Enter}{/Control}') - await user.type(document.querySelectorAll('[contenteditable="true"]')[1], 'To Do') - await act(vi.runOnlyPendingTimersAsync) + // we create a `Home` thought + await user.keyboard('{Enter}') + await user.type(lastThought(), 'Home') + await act(vi.runOnlyPendingTimersAsync) + ensureStep(TUTORIAL2_STEP_CONTEXT1) - expect(screen.getByText(/Now add a thought to “To Do”/)).toBeInTheDocument() + // Home -> To Do + expect(screen.getByText(/Let's say that you want to make a list of things/)).toBeInTheDocument() + expect(screen.getByText(/Add a thought with the text "To Do"/)).toBeInTheDocument() + await user.keyboard('{Control>}{Enter}{/Control}') + await user.type(lastThought(), 'To Do') + await act(vi.runOnlyPendingTimersAsync) + ensureStep(TUTORIAL2_STEP_CONTEXT1_SUBTHOUGHT) - await user.keyboard('{Control>}{Enter}{/Control}') - await act(vi.runOnlyPendingTimersAsync) - await user.type(lastThought(), 'or to not') - await act(vi.runOnlyPendingTimersAsync) + // Home -> To Do -> or to not + expect(screen.getByText(/Now add a thought to “To Do”/)).toBeInTheDocument() + await user.keyboard('{Control>}{Enter}{/Control}') + await user.type(lastThought(), 'or to not') + await act(vi.runOnlyPendingTimersAsync) - expect(showAllThoughts()).toBe( - `- __ROOT__ + expect(exportContext(store.getState(), [HOME_TOKEN], 'text/plain')).toBe( + `- __ROOT__ - Home - To Do - or to not`, - ) - expect(screen.getByText(/Nice work!/)).toBeInTheDocument() - }) + ) + expect(screen.getByText(/Nice work!/)).toBeInTheDocument() }) - describe('step context 2', async () => { - beforeEach(createTestAppWithTutorial) - - it('prompt for creating a second todo, shows a superscript', async () => { - await user.click(screen.getByText('Next')) - expect(screen.getByText(/Now we are going to create a different "To Do" list./)).toBeInTheDocument() - - await user.keyboard('{Enter}') - await user.keyboard('{Shift>}{Tab}{/Shift}') // we are at - await user.keyboard('{Shift>}{Tab}{/Shift}') - - await act(vi.runOnlyPendingTimersAsync) - - await user.type(lastThought(), 'Work') - await act(vi.runOnlyPendingTimersAsync) + it('step context 2 - we create "Work" thought with children', async () => { + await user.click(screen.getByText('Next')) + ensureStep(TUTORIAL2_STEP_CONTEXT2_PARENT) + expect(screen.getByText(/Now we are going to create a different "To Do" list./)).toBeInTheDocument() - expect(screen.getByText('Now add a thought with the text "To Do"', { exact: false })).toBeInTheDocument() + // we created a new thought on 3rd level, so we shift-tab our way back to root + await user.keyboard('{Enter}') + await user.keyboard('{Shift>}{Tab}{/Shift}') + await user.keyboard('{Shift>}{Tab}{/Shift}') + await user.type(lastThought(), 'Work') + await act(vi.runOnlyPendingTimersAsync) - await user.keyboard('{Control>}{Enter}{/Control}') - await user.type(lastThought(), 'To Do') + expect(screen.getByText('Now add a thought with the text "To Do"', { exact: false })).toBeInTheDocument() + await user.keyboard('{Control>}{Enter}{/Control}') + await user.type(lastThought(), 'To Do') - expect(showAllThoughts()).toBe( - `- __ROOT__ + expect(exportContext(store.getState(), [HOME_TOKEN], 'text/plain')).toBe( + `- __ROOT__ - Home - To Do - or to not - Work - To Do`, - ) - expect(screen.getByText('Very good!')).toBeInTheDocument() + ) + expect(screen.getByText('Very good!')).toBeInTheDocument() - expect(screen.getAllByRole('superscript')[0]).toHaveTextContent('2') - expect(screen.getByText('This means that “To Do” appears in two places', { exact: false })).toBeInTheDocument() + expect(screen.getAllByRole('superscript')[0]).toHaveTextContent('2') + expect(screen.getByText('This means that “To Do” appears in two places', { exact: false })).toBeInTheDocument() - expect(screen.getByText('Imagine a new work task. Add it to this “To Do” list.')) - await user.keyboard('{Control>}{Enter}{/Control}') - await user.type(lastThought(), 'new work task') - }) + expect(screen.getByText('Imagine a new work task. Add it to this “To Do” list.')) + await user.keyboard('{Control>}{Enter}{/Control}') + await user.type(lastThought(), 'new work task') }) - describe('multiple contexts', () => { - beforeEach(createTestAppWithTutorial) - it('step context view open - showcase multiple contexts', async () => { - expect(showAllThoughts()).toBe( - `- __ROOT__ + it('step context view open - we press Alt+Shift+S and see "To Do" in both "Home" and "Work"', async () => { + expect(exportContext(store.getState(), [HOME_TOKEN], 'text/plain')).toBe( + `- __ROOT__ - Home - To Do - or to not - Work - To Do - new work task`, - ) - await user.click(screen.getByText('Next')) - await act(vi.runOnlyPendingTimersAsync) - - expect(screen.getByText(/First select "To Do"./)).toBeInTheDocument() - - console.log(screen.getAllByText('To Do').at(-1)!) - await user.keyboard('{Escape}') // focus out - await user.click(screen.getAllByText('To Do').at(-1)!) // and click on To Do - - await act(vi.runOnlyPendingTimersAsync) - - // await user.click(screen.getAllByText('To Do').at(-1)!) // focus on - await act(vi.runOnlyPendingTimersAsync) - - // await dispatch(setCursorFirstMatch(['Work', 'To Do'])) - showAllThoughts() - - await act(vi.runOnlyPendingTimersAsync) - expect(screen.getByText("Hit Alt + Shift + S to view the current thought's contexts.")).toBeInTheDocument() + ) + await user.click(screen.getByText('Next')) + await act(vi.runOnlyPendingTimersAsync) - await user.keyboard('{Alt>}{Shift>}S{/Shift}{/Alt}') - await act(vi.runOnlyPendingTimersAsync) + ensureStep(TUTORIAL2_STEP_CONTEXT_VIEW_SELECT) + expect(screen.getByText(/First select "To Do"./)).toBeInTheDocument() + await user.keyboard('{Escape}') // focus out + await user.click(screen.getAllByText('To Do').at(-1)!) // and click on To Do + await act(vi.runOnlyPendingTimersAsync) - expect( - screen.getByText( - `Well, look at that. We now see all of the contexts in which "To Do" appears, namely "Home" and "Work".`, - ), - ).toBeInTheDocument() - }) + expect(screen.getByText("Hit Alt + Shift + S to view the current thought's contexts.")).toBeInTheDocument() + await user.keyboard('{Alt>}{Shift>}S{/Shift}{/Alt}') + await act(vi.runOnlyPendingTimersAsync) + ensureStep(TUTORIAL2_STEP_CONTEXT_VIEW_OPEN) + expect( + screen.getByText( + `Well, look at that. We now see all of the contexts in which "To Do" appears, namely "Home" and "Work".`, + ), + ).toBeInTheDocument() }) - describe('step context examples - show real world examples', async () => { - beforeEach(createTestAppWithTutorial) - - it('show real world examples', async () => { - await user.click(screen.getByText('Next')) - expect( - screen.getByText('Here are some real-world examples of using contexts in', { exact: false }), - ).toBeInTheDocument() - expect(screen.getByText('View all thoughts related to a particular person, place, or thing.')).toBeInTheDocument() - expect(screen.getByText('Keep track of quotations from different sources.')).toBeInTheDocument() - expect( - screen.getByText('Create a link on the home screen to a deeply nested subthought for easy access.'), - ).toBeInTheDocument() - }) + it('step context examples - we see real-world examples', async () => { + await user.click(screen.getByText('Next')) + ensureStep(TUTORIAL2_STEP_CONTEXT_VIEW_EXAMPLES) + expect(screen.getByText(/Here are some real-world examples of using contexts in/)).toBeInTheDocument() + expect(screen.getByText('View all thoughts related to a particular person, place, or thing.')).toBeInTheDocument() + expect(screen.getByText('Keep track of quotations from different sources.')).toBeInTheDocument() }) - describe('step success', async () => { - beforeEach(createTestAppWithTutorial) - - it('congratulates on finishing tutorial, hides it after "Finish"', async () => { - await user.click(screen.getByText('Next')) - expect( - screen.getByText('Congratulations! You have completed Part II of the tutorial.', { exact: false }), - ).toBeInTheDocument() + it('step success - congratulations, hide tutorial after clicking "Finish"', async () => { + await user.click(screen.getByText('Next')) + expect(screen.getByText(/Congratulations! You have completed Part II of the tutorial./)).toBeInTheDocument() - user.click(screen.getByText('Finish')) - await act(vi.runOnlyPendingTimersAsync) + user.click(screen.getByText('Finish')) + await act(vi.runOnlyPendingTimersAsync) - expect(() => screen.getByTestId('tutorial-step')).toThrow('Unable to find an element') - }) + expect(() => screen.getByTestId('tutorial-step')).toThrow('Unable to find an element') }) }) - -function showAllThoughts( - logPostfix: string = '', // to differentiate between different tests -) { - const exported = exportContext(store.getState(), [HOME_TOKEN], 'text/plain') - console.log(`${exported} ${logPostfix}`) - - return exported -} - -function lastThought() { - return Array.from(document.querySelectorAll('[contenteditable="true"]')).at(-1)! -} diff --git a/src/test-helpers/createTestApp.tsx b/src/test-helpers/createTestApp.tsx index 9090eeeccb..8eff0841d7 100644 --- a/src/test-helpers/createTestApp.tsx +++ b/src/test-helpers/createTestApp.tsx @@ -13,10 +13,9 @@ import storage from '../util/storage' let cleanup: Await>['cleanup'] /** Set up testing and mock document and window functions. */ -const createTestApp = async ({ tutorial = false } = {}) => { +const createTestApp = async ({ tutorial } = { tutorial: false }) => { await act(async () => { vi.useFakeTimers({ loopLimit: 100000 }) - // calls initEvents, which must be manually cleaned up const init = await initialize() cleanup = init.cleanup @@ -47,9 +46,6 @@ const createTestApp = async ({ tutorial = false } = {}) => { }) } -/** Set up testing and mock document and window functions, and show tutorial. */ -export const createTestAppWithTutorial = () => createTestApp({ tutorial: true }) - /** Clear store, localStorage, local db, and window event handlers. */ export const cleanupTestApp = async () => { await act(async () => { @@ -83,4 +79,13 @@ export const refreshTestApp = async () => { await act(vi.runOnlyPendingTimersAsync) } +/** Clear exisiting event listeners, but without clearing the app. */ +export const cleanupTestEventHandlers = async () => { + await act(async () => { + if (cleanup) { + cleanup() + } + }) +} + export default createTestApp