chore: clenaup unit tests

This commit is contained in:
Mário Nunes
2024-06-15 14:25:07 +01:00
parent a5490e576c
commit a1225bca54
37 changed files with 431 additions and 372 deletions

View File

@@ -43,9 +43,9 @@ describe('SEO', () => {
beforeAll(async () => { beforeAll(async () => {
db = admin.firestore() db = admin.firestore()
// Test will only create entries for accepted howtos and research // Test will only create entries for accepted howtos and research
for (const doc of testDocs) { await Promise.all(
await db.collection(doc.endpoint).add(doc) testDocs.map((doc) => db.collection(doc.endpoint).add(doc)),
} )
}) })
afterAll(firebaseTest.cleanup) afterAll(firebaseTest.cleanup)

View File

@@ -1,6 +1,6 @@
import '@testing-library/jest-dom/vitest' import '@testing-library/jest-dom/vitest'
import { fireEvent, waitFor } from '@testing-library/react' import { fireEvent } from '@testing-library/react'
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { render } from '../test/utils' import { render } from '../test/utils'
@@ -60,12 +60,10 @@ describe('CreateReply', () => {
fireEvent.click(submitButton) fireEvent.click(submitButton)
await waitFor(() => { expect(
expect( screen.getByText(
screen.getByText( 'Unable to leave a comment at this time. Please try again later.',
'Unable to leave a comment at this time. Please try again later.', ),
), ).toBeInTheDocument()
).toBeInTheDocument()
})
}) })
}) })

View File

@@ -17,27 +17,27 @@ describe('DiscussionContainer', () => {
expect(() => getByText('reply')).toThrow() expect(() => getByText('reply')).toThrow()
}) })
it('allows replying to a comment', async () => { it('allows replying to a comment', () => {
const screen = render(<WithReplies.render />) const screen = render(<WithReplies.render />)
// Show reply form // Show reply form
await act(async () => { act(() => {
const replyButton = screen.getAllByText('2 replies to', { const replyButton = screen.getAllByText('2 replies to', {
exact: false, exact: false,
})[0] })[0]
expect(replyButton).toBeInTheDocument() expect(replyButton).toBeInTheDocument()
await fireEvent.click(replyButton) fireEvent.click(replyButton)
expect(screen.getAllByText('Leave a reply')).toHaveLength(1) expect(screen.getAllByText('Leave a reply')).toHaveLength(1)
}) })
// Hide reply form // Hide reply form
await act(async () => { act(() => {
const replyButton = screen.getAllByText('2 replies to', { const replyButton = screen.getAllByText('2 replies to', {
exact: false, exact: false,
})[0] })[0]
await fireEvent.click(replyButton) fireEvent.click(replyButton)
expect(() => { expect(() => {
screen.getAllByText('Leave a reply') screen.getAllByText('Leave a reply')
}).toThrow() }).toThrow()
@@ -49,14 +49,14 @@ describe('DiscussionContainer', () => {
expect(SecondReplyButton).toBeInTheDocument() expect(SecondReplyButton).toBeInTheDocument()
// Show reply form // Show reply form
await act(async () => { act(() => {
await fireEvent.click(SecondReplyButton) fireEvent.click(SecondReplyButton)
expect(screen.getAllByText('Leave a reply')).toHaveLength(1) expect(screen.getAllByText('Leave a reply')).toHaveLength(1)
}) })
// Hide reply form // Hide reply form
await act(async () => { act(() => {
await fireEvent.click(SecondReplyButton) fireEvent.click(SecondReplyButton)
expect(() => { expect(() => {
screen.getAllByText('Send your reply') screen.getAllByText('Send your reply')
}).toThrow() }).toThrow()

View File

@@ -29,7 +29,7 @@ describe('DonationRequest', () => {
expect(iframe).toHaveAttribute('src', iframeSrc) expect(iframe).toHaveAttribute('src', iframeSrc)
}) })
it('calls the callback when user skips', async () => { it('calls the callback when user skips', () => {
const body = 'All of the content here is free.' const body = 'All of the content here is free.'
const mockCallback = vi.fn() const mockCallback = vi.fn()

View File

@@ -59,7 +59,7 @@ describe('EditComment', () => {
) )
expect(screen.getByTestId('edit-comment-submit')).toBeDisabled() expect(screen.getByTestId('edit-comment-submit')).toBeDisabled()
}) })
it('should dispaly error message when the comment is empty', async () => { it('should dispaly error message when the comment is empty', () => {
const screen = render( const screen = render(
<EditComment <EditComment
isReply={false} isReply={false}
@@ -69,7 +69,7 @@ describe('EditComment', () => {
/>, />,
) )
await act(async () => { act(() => {
const commentInput = screen.getByLabelText('Edit Comment') const commentInput = screen.getByLabelText('Edit Comment')
fireEvent.change(commentInput, { target: { value: '' } }) fireEvent.change(commentInput, { target: { value: '' } })
fireEvent.blur(commentInput) fireEvent.blur(commentInput)

View File

@@ -156,7 +156,7 @@ describe('ImageGallery', () => {
expect(image?.getAttribute('src')).toEqual(testImages[0].downloadUrl) expect(image?.getAttribute('src')).toEqual(testImages[0].downloadUrl)
}) })
it('hides thumbnail for single image', async () => { it('hides thumbnail for single image', () => {
const { getAllByTestId } = render( const { getAllByTestId } = render(
<HideThumbnailForSingleImage <HideThumbnailForSingleImage
{...(HideThumbnailForSingleImage.args as ImageGalleryProps)} {...(HideThumbnailForSingleImage.args as ImageGalleryProps)}
@@ -168,7 +168,7 @@ describe('ImageGallery', () => {
}).toThrow() }).toThrow()
}) })
it('supports no thumbnail option', async () => { it('supports no thumbnail option', () => {
const { getAllByTestId } = render( const { getAllByTestId } = render(
<NoThumbnails {...(NoThumbnails.args as ImageGalleryProps)} />, <NoThumbnails {...(NoThumbnails.args as ImageGalleryProps)} />,
) )
@@ -178,7 +178,7 @@ describe('ImageGallery', () => {
}).toThrow() }).toThrow()
}) })
it('supports show next/previous buttons', async () => { it('supports show next/previous buttons', () => {
const { getByRole } = render( const { getByRole } = render(
<ShowNextPrevButtons <ShowNextPrevButtons
{...(ShowNextPrevButtons.args as ImageGalleryProps)} {...(ShowNextPrevButtons.args as ImageGalleryProps)}
@@ -192,7 +192,7 @@ describe('ImageGallery', () => {
expect(previousBtn).toBeInTheDocument() expect(previousBtn).toBeInTheDocument()
}) })
it('does not support show next/previous buttons because only one image', async () => { it('does not support show next/previous buttons because only one image', () => {
const { queryByRole } = render( const { queryByRole } = render(
<DoNotShowNextPrevButtons <DoNotShowNextPrevButtons
{...(DoNotShowNextPrevButtons.args as ImageGalleryProps)} {...(DoNotShowNextPrevButtons.args as ImageGalleryProps)}

View File

@@ -16,7 +16,7 @@ describe('MapMemberCard', () => {
expect(() => getByTestId('MapMemberCard: moderation comments')).toThrow() expect(() => getByTestId('MapMemberCard: moderation comments')).toThrow()
}) })
it('shows moderation comments if they exist', async () => { it('shows moderation comments if they exist', () => {
const { getByText, getByTestId } = render( const { getByText, getByTestId } = render(
<MapMemberCard {...ModerationComments.args} />, <MapMemberCard {...ModerationComments.args} />,
) )

View File

@@ -15,10 +15,10 @@ describe('TabbedContent', () => {
expect(() => wrapper.getByText('Tab Panel #2')).toThrow() expect(() => wrapper.getByText('Tab Panel #2')).toThrow()
}) })
it('basic interaction', async () => { it('basic interaction', () => {
const wrapper = render(<Default />) const wrapper = render(<Default />)
await act(async () => { act(() => {
wrapper.getByText('Tab #2').click() wrapper.getByText('Tab #2').click()
}) })

View File

@@ -28,7 +28,7 @@ vi.mock('src/common/hooks/useCommonStores', () => ({
// Happy path well tested in cypress // Happy path well tested in cypress
describe('DiscussionWrapper', () => { describe('DiscussionWrapper', () => {
it('initally renders a loading before moving on', async () => { it('initally renders a loading before moving on', () => {
const discussionProps = { const discussionProps = {
sourceType: 'question' as IDiscussion['sourceType'], sourceType: 'question' as IDiscussion['sourceType'],
sourceId: '82364tdf', sourceId: '82364tdf',
@@ -47,7 +47,7 @@ describe('DiscussionWrapper', () => {
}) })
expect(wrapper.getByTestId('loader')).toBeVisible() expect(wrapper.getByTestId('loader')).toBeVisible()
await waitFor(async () => { waitFor(() => {
expect(wrapper.getByText('Start the discussion')).toBeVisible() expect(wrapper.getByText('Start the discussion')).toBeVisible()
}) })
}) })

View File

@@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest'
import { HideDiscussionContainer } from './HideDiscussionContainer' import { HideDiscussionContainer } from './HideDiscussionContainer'
describe('HideDiscussionContainer', () => { describe('HideDiscussionContainer', () => {
it('can be opened/closed', async () => { it('can be opened/closed', () => {
const { getByText } = render( const { getByText } = render(
<HideDiscussionContainer commentCount={0}> <HideDiscussionContainer commentCount={0}>
<>Hidden</> <>Hidden</>

View File

@@ -13,14 +13,14 @@ vi.mock('react-router-dom', async () => ({
})) }))
describe('ScrollToTop', () => { describe('ScrollToTop', () => {
it('should scroll to top when pathname changes', async () => { it('should scroll to top when pathname changes', () => {
const scrollToSpy = vi.fn() const scrollToSpy = vi.fn()
global.window.scrollTo = scrollToSpy global.window.scrollTo = scrollToSpy
;(useLocation as Mock).mockImplementation(() => ({ ;(useLocation as Mock).mockImplementation(() => ({
pathname: '/initial', pathname: '/initial',
})) }))
await act(async () => { act(() => {
render(<ScrollToTop />) render(<ScrollToTop />)
}) })
@@ -34,7 +34,7 @@ describe('ScrollToTop', () => {
pathname: '/changed', pathname: '/changed',
})) }))
await act(async () => { act(() => {
render(<ScrollToTop />) render(<ScrollToTop />)
}) })

View File

@@ -31,7 +31,7 @@ describe('HowtoCategoryGuidance', () => {
await screen.findByText(filesGuidance, { exact: false }) await screen.findByText(filesGuidance, { exact: false })
}) })
it('renders nothing when not visible', async () => { it('renders nothing when not visible', () => {
const { container } = render( const { container } = render(
<HowtoProvider> <HowtoProvider>
<HowtoCategoryGuidance category={undefined} type="main" /> <HowtoCategoryGuidance category={undefined} type="main" />

View File

@@ -38,7 +38,7 @@ describe('HowtoErrors', () => {
await screen.findByText('Step 2') await screen.findByText('Step 2')
}) })
it('renders nothing when not visible', async () => { it('renders nothing when not visible', () => {
const errors = { const errors = {
title: 'Make sure this field is filled correctly', title: 'Make sure this field is filled correctly',
} }

View File

@@ -8,7 +8,7 @@ import {
} from 'react-router-dom' } from 'react-router-dom'
import { ThemeProvider } from '@emotion/react' import { ThemeProvider } from '@emotion/react'
import { faker } from '@faker-js/faker' import { faker } from '@faker-js/faker'
import { act, render, within } from '@testing-library/react' import { act, render, waitFor, within } from '@testing-library/react'
import { Provider } from 'mobx-react' import { Provider } from 'mobx-react'
import { preciousPlasticTheme } from 'oa-themes' import { preciousPlasticTheme } from 'oa-themes'
import { FactoryHowto, FactoryHowtoStep } from 'src/test/factories/Howto' import { FactoryHowto, FactoryHowtoStep } from 'src/test/factories/Howto'
@@ -50,7 +50,7 @@ import { IModerationStatus } from 'oa-shared'
import { Howto } from './Howto' import { Howto } from './Howto'
const factory = async (howtoStore?: Partial<HowtoStore>) => { const factory = (howtoStore?: Partial<HowtoStore>) => {
const router = createMemoryRouter( const router = createMemoryRouter(
createRoutesFromElements( createRoutesFromElements(
<Route path="/howto/:slug" key={1} element={<Howto />} />, <Route path="/howto/:slug" key={1} element={<Howto />} />,
@@ -70,69 +70,73 @@ const factory = async (howtoStore?: Partial<HowtoStore>) => {
} }
describe('Howto', () => { describe('Howto', () => {
describe('moderator feedback', () => { describe('moderator feedback', () => {
it('displays feedback for items which are not accepted', async () => { it('displays feedback for items which are not accepted', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto.moderation = IModerationStatus.AWAITING_MODERATION howto.moderation = IModerationStatus.AWAITING_MODERATION
howto.moderatorFeedback = 'Moderation comments' howto.moderatorFeedback = 'Moderation comments'
wrapper = await factory() wrapper = factory()
}) })
expect(wrapper.getByText('Moderation comments')).toBeInTheDocument() waitFor(() => {
expect(wrapper.getByText('Moderation comments')).toBeInTheDocument()
})
}) })
it('hides feedback when how-to is accepted', async () => { it('hides feedback when how-to is accepted', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto.moderation = IModerationStatus.ACCEPTED howto.moderation = IModerationStatus.ACCEPTED
howto.moderatorFeedback = 'Moderation comments' howto.moderatorFeedback = 'Moderation comments'
wrapper = await factory() wrapper = factory()
}) })
expect(() => wrapper.getByText('Moderation comments')).toThrow() expect(() => wrapper.getByText('Moderation comments')).toThrow()
}) })
}) })
it('displays content statistics', async () => { it('displays content statistics', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto._id = 'testid' howto._id = 'testid'
howto._createdBy = 'HowtoAuthor' howto._createdBy = 'HowtoAuthor'
howto.steps = [FactoryHowtoStep({})] howto.steps = [FactoryHowtoStep({})]
howto.moderation = IModerationStatus.ACCEPTED howto.moderation = IModerationStatus.ACCEPTED
howto.total_views = 0 howto.total_views = 0
wrapper = await factory() wrapper = factory()
}) })
expect(wrapper.getByText('0 views')).toBeInTheDocument() waitFor(() => {
expect(wrapper.getByText('0 useful')).toBeInTheDocument() expect(wrapper.getByText('0 views')).toBeInTheDocument()
expect(wrapper.getByText('0 comments')).toBeInTheDocument() expect(wrapper.getByText('0 useful')).toBeInTheDocument()
expect(wrapper.getByText('1 step')).toBeInTheDocument() expect(wrapper.getByText('0 comments')).toBeInTheDocument()
expect(wrapper.getByText('1 step')).toBeInTheDocument()
})
}) })
it('shows verified badge', async () => { it('shows verified badge', () => {
let wrapper let wrapper
howto._createdBy = 'HowtoAuthor' howto._createdBy = 'HowtoAuthor'
await act(async () => { act(() => {
wrapper = await factory() wrapper = factory()
}) })
expect(() => { waitFor(() => {
wrapper.getAllByTestId('Username: verified badge') expect(() => wrapper.getAllByTestId('Username: verified badge'))
}).not.toThrow() })
}) })
it('does not show verified badge', async () => { it('does not show verified badge', () => {
let wrapper let wrapper
howto._createdBy = 'NotHowtoAuthor' howto._createdBy = 'NotHowtoAuthor'
await act(async () => { act(() => {
wrapper = await factory() wrapper = factory()
}) })
expect(() => { expect(() => {
@@ -141,10 +145,10 @@ describe('Howto', () => {
}) })
describe('steps', () => { describe('steps', () => {
it('shows 1 step', async () => { it('shows 1 step', () => {
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await factory({ wrapper = factory({
...mockHowtoStore(), ...mockHowtoStore(),
activeHowto: FactoryHowto({ activeHowto: FactoryHowto({
_createdBy: 'HowtoAuthor', _createdBy: 'HowtoAuthor',
@@ -153,28 +157,28 @@ describe('Howto', () => {
}) })
}) })
expect(() => { waitFor(() => {
wrapper.getAllByText('1 step') expect(() => wrapper.getAllByText('1 step'))
}).not.toThrow() })
}) })
it('shows 2 steps', async () => { it('shows 2 steps', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto.steps = [FactoryHowtoStep(), FactoryHowtoStep()] howto.steps = [FactoryHowtoStep(), FactoryHowtoStep()]
wrapper = await factory() wrapper = factory()
}) })
expect(() => { waitFor(() => {
wrapper.getAllByText('2 steps') expect(() => wrapper.getAllByText('2 steps'))
}).not.toThrow() })
}) })
}) })
describe('Breadcrumbs', () => { describe('Breadcrumbs', () => {
it('displays breadcrumbs with category', async () => { it('displays breadcrumbs with category', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto.title = 'DIY Recycling Machine' howto.title = 'DIY Recycling Machine'
howto.category = { howto.category = {
label: 'DIY', label: 'DIY',
@@ -184,10 +188,10 @@ describe('Howto', () => {
_deleted: faker.datatype.boolean(), _deleted: faker.datatype.boolean(),
_contentModifiedTimestamp: faker.date.past().toString(), _contentModifiedTimestamp: faker.date.past().toString(),
} }
wrapper = await factory() wrapper = factory()
}) })
expect(() => { waitFor(() => {
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems).toHaveLength(3) expect(breadcrumbItems).toHaveLength(3)
expect(breadcrumbItems[0]).toHaveTextContent('How To') expect(breadcrumbItems[0]).toHaveTextContent('How To')
@@ -203,18 +207,18 @@ describe('Howto', () => {
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(2) expect(chevrons).toHaveLength(2)
}).not.toThrow() })
}) })
it('displays breadcrumbs without category', async () => { it('displays breadcrumbs without category', () => {
let wrapper let wrapper
await act(async () => { act(() => {
howto.title = 'DIY Recycling Machine' howto.title = 'DIY Recycling Machine'
howto.category = undefined howto.category = undefined
wrapper = await factory() wrapper = factory()
}) })
expect(() => { waitFor(() => {
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems).toHaveLength(2) expect(breadcrumbItems).toHaveLength(2)
expect(breadcrumbItems[0]).toHaveTextContent('How To') expect(breadcrumbItems[0]).toHaveTextContent('How To')
@@ -227,7 +231,7 @@ describe('Howto', () => {
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(1) expect(chevrons).toHaveLength(1)
}).not.toThrow() })
}) })
}) })
}) })

View File

@@ -40,7 +40,7 @@ vi.mock('../../config/config', () => ({
})) }))
describe('howtos.search', () => { describe('howtos.search', () => {
it('searches for text', async () => { it('searches for text', () => {
// prepare // prepare
const words = ['test', 'text'] const words = ['test', 'text']
@@ -61,7 +61,7 @@ describe('howtos.search', () => {
) )
}) })
it('filters by category', async () => { it('filters by category', () => {
// prepare // prepare
const category = 'cat1' const category = 'cat1'
@@ -78,7 +78,7 @@ describe('howtos.search', () => {
expect(mockWhere).toHaveBeenCalledWith('category._id', '==', category) expect(mockWhere).toHaveBeenCalledWith('category._id', '==', category)
}) })
it('should not call orderBy if sorting by most relevant', async () => { it('should not call orderBy if sorting by most relevant', () => {
// act // act
exportedForTesting.createQueries( exportedForTesting.createQueries(
['test'], ['test'],
@@ -92,7 +92,7 @@ describe('howtos.search', () => {
expect(mockOrderBy).toHaveBeenCalledTimes(0) expect(mockOrderBy).toHaveBeenCalledTimes(0)
}) })
it('should call orderBy when sorting is not MostRelevant', async () => { it('should call orderBy when sorting is not MostRelevant', () => {
// act // act
exportedForTesting.createQueries( exportedForTesting.createQueries(
['test'], ['test'],

View File

@@ -51,7 +51,7 @@ vi.mock('src/common/hooks/useCommonStores', () => ({
})) }))
describe('Maps', () => { describe('Maps', () => {
it('prompts on load for user current position', async () => { it('prompts on load for user current position', () => {
Object.defineProperty(global.navigator, 'geolocation', { Object.defineProperty(global.navigator, 'geolocation', {
writable: true, writable: true,
value: { value: {
@@ -59,28 +59,30 @@ describe('Maps', () => {
}, },
}) })
await act(async () => { act(() => {
await Wrapper() Wrapper()
}) })
expect(global.navigator.geolocation.getCurrentPosition).toBeCalled() waitFor(() => {
expect(global.navigator.geolocation.getCurrentPosition).toBeCalled()
})
}) })
it('loads individual map card', async () => { it('loads individual map card', () => {
let wrapper: any let wrapper: any
await act(async () => { act(() => {
wrapper = await Wrapper('/map#abc') wrapper = Wrapper('/map#abc')
}) })
await waitFor(async () => { waitFor(() => {
expect(wrapper.mockMapPinService.getMapPinByUserId).toBeCalledWith('abc') expect(wrapper.mockMapPinService.getMapPinByUserId).toBeCalledWith('abc')
expect(wrapper.renderResult.getByText('description')).toBeInTheDocument() expect(wrapper.renderResult.getByText('description')).toBeInTheDocument()
}) })
}) })
}) })
const Wrapper = async (path = '/map') => { const Wrapper = (path = '/map') => {
const router = createMemoryRouter( const router = createMemoryRouter(
createRoutesFromElements(<Route path="/map" element={<Maps />} />), createRoutesFromElements(<Route path="/map" element={<Maps />} />),
{ {

View File

@@ -8,7 +8,7 @@ import {
} from 'react-router-dom' } from 'react-router-dom'
import { ThemeProvider } from '@emotion/react' import { ThemeProvider } from '@emotion/react'
import { faker } from '@faker-js/faker' import { faker } from '@faker-js/faker'
import { act, render, within } from '@testing-library/react' import { act, render, waitFor, within } from '@testing-library/react'
import { Provider } from 'mobx-react' import { Provider } from 'mobx-react'
import { UserRole } from 'oa-shared' import { UserRole } from 'oa-shared'
import { useQuestionStore } from 'src/stores/Question/question.store' import { useQuestionStore } from 'src/stores/Question/question.store'
@@ -84,7 +84,7 @@ describe('Questions', () => {
}) })
describe('Breadcrumbs', () => { describe('Breadcrumbs', () => {
it('displays breadcrumbs with category', async () => { it('displays breadcrumbs with category', () => {
// Arrange // Arrange
mockQuestionItem.title = mockQuestionItem.title =
'Do you prefer camping near a lake or in a forest?' 'Do you prefer camping near a lake or in a forest?'
@@ -106,31 +106,33 @@ describe('Questions', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert: Check the breadcrumb items and chevrons // Assert: Check the breadcrumb items and chevrons
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') waitFor(() => {
expect(breadcrumbItems).toHaveLength(3) const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems[0]).toHaveTextContent('Question') expect(breadcrumbItems).toHaveLength(3)
expect(breadcrumbItems[1]).toHaveTextContent('Preference') expect(breadcrumbItems[0]).toHaveTextContent('Question')
expect(breadcrumbItems[2]).toHaveTextContent( expect(breadcrumbItems[1]).toHaveTextContent('Preference')
'Do you prefer camping near a lake or in a forest?', expect(breadcrumbItems[2]).toHaveTextContent(
) 'Do you prefer camping near a lake or in a forest?',
)
// Assert: Check that the first two breadcrumb items contain links // Assert: Check that the first two breadcrumb items contain links
const firstLink = within(breadcrumbItems[0]).getByRole('link') const firstLink = within(breadcrumbItems[0]).getByRole('link')
const secondLink = within(breadcrumbItems[1]).getByRole('link') const secondLink = within(breadcrumbItems[1]).getByRole('link')
expect(firstLink).toBeInTheDocument() expect(firstLink).toBeInTheDocument()
expect(secondLink).toBeInTheDocument() expect(secondLink).toBeInTheDocument()
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(2) expect(chevrons).toHaveLength(2)
})
}) })
it('displays breadcrumbs without category', async () => { it('displays breadcrumbs without category', () => {
// Arrange // Arrange
mockQuestionItem.title = mockQuestionItem.title =
'Do you prefer camping near a lake or in a forest?' 'Do you prefer camping near a lake or in a forest?'
@@ -145,25 +147,27 @@ describe('Questions', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert: Check the breadcrumb items and chevrons // Assert: Check the breadcrumb items and chevrons
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') waitFor(() => {
expect(breadcrumbItems).toHaveLength(2) const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems[0]).toHaveTextContent('Question') expect(breadcrumbItems).toHaveLength(2)
expect(breadcrumbItems[1]).toHaveTextContent( expect(breadcrumbItems[0]).toHaveTextContent('Question')
'Do you prefer camping near a lake or in a forest?', expect(breadcrumbItems[1]).toHaveTextContent(
) 'Do you prefer camping near a lake or in a forest?',
)
// Assert: Check that the first breadcrumb item contains a link // Assert: Check that the first breadcrumb item contains a link
const firstLink = within(breadcrumbItems[0]).getByRole('link') const firstLink = within(breadcrumbItems[0]).getByRole('link')
expect(firstLink).toBeInTheDocument() expect(firstLink).toBeInTheDocument()
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(1) expect(chevrons).toHaveLength(1)
})
}) })
}) })
}) })

View File

@@ -144,14 +144,14 @@ describe('question.routes', () => {
expect(wrapper.getByText(/loading/)).toBeInTheDocument() expect(wrapper.getByText(/loading/)).toBeInTheDocument()
}) })
it('renders an empty state', async () => { it('renders an empty state', () => {
let wrapper let wrapper
act(() => { act(() => {
wrapper = renderFn('/questions') wrapper = renderFn('/questions')
}) })
await waitFor(async () => { waitFor(() => {
expect( expect(
wrapper.getByText(/Ask your questions and help others out/), wrapper.getByText(/Ask your questions and help others out/),
).toBeInTheDocument() ).toBeInTheDocument()
@@ -469,7 +469,7 @@ describe('question.routes', () => {
) )
}) })
it('redirects non-author', async () => { it('redirects non-author', () => {
let wrapper let wrapper
mockActiveUser = FactoryUser({ userName: 'not-author' }) mockActiveUser = FactoryUser({ userName: 'not-author' })
;(useQuestionStore as Mock).mockReturnValue({ ;(useQuestionStore as Mock).mockReturnValue({
@@ -487,7 +487,7 @@ describe('question.routes', () => {
wrapper = renderFn('/questions/slug/edit') wrapper = renderFn('/questions/slug/edit')
}) })
await waitFor(async () => { waitFor(() => {
expect(() => wrapper.getByText(editFormTitle)).toThrow() expect(() => wrapper.getByText(editFormTitle)).toThrow()
expect(mockedUsedNavigate).toBeCalledWith('/questions/slug') expect(mockedUsedNavigate).toBeCalledWith('/questions/slug')
}) })

View File

@@ -36,7 +36,7 @@ vi.mock('../../config/config', () => ({
})) }))
describe('question.search', () => { describe('question.search', () => {
it('searches for text', async () => { it('searches for text', () => {
// prepare // prepare
const words = ['test', 'text'] const words = ['test', 'text']
@@ -51,7 +51,7 @@ describe('question.search', () => {
) )
}) })
it('filters by category', async () => { it('filters by category', () => {
// prepare // prepare
const category = 'cat1' const category = 'cat1'
@@ -66,7 +66,7 @@ describe('question.search', () => {
) )
}) })
it('should not call orderBy if sorting by most relevant', async () => { it('should not call orderBy if sorting by most relevant', () => {
// act // act
exportedForTesting.createQueries(['test'], '', 'MostRelevant') exportedForTesting.createQueries(['test'], '', 'MostRelevant')
@@ -74,7 +74,7 @@ describe('question.search', () => {
expect(mockOrderBy).toHaveBeenCalledTimes(0) expect(mockOrderBy).toHaveBeenCalledTimes(0)
}) })
it('should call orderBy when sorting is not MostRelevant', async () => { it('should call orderBy when sorting is not MostRelevant', () => {
// act // act
exportedForTesting.createQueries(['test'], '', 'Newest') exportedForTesting.createQueries(['test'], '', 'Newest')
@@ -82,7 +82,7 @@ describe('question.search', () => {
expect(mockOrderBy).toHaveBeenLastCalledWith('_created', 'desc') expect(mockOrderBy).toHaveBeenLastCalledWith('_created', 'desc')
}) })
it('should limit results', async () => { it('should limit results', () => {
// prepare // prepare
const take = 12 const take = 12

View File

@@ -27,7 +27,7 @@ describe('ResearchErrors', () => {
await screen.findByText(descriptionTitle, { exact: false }) await screen.findByText(descriptionTitle, { exact: false })
}) })
it('renders nothing when not visible', async () => { it('renders nothing when not visible', () => {
const errors = {} const errors = {}
const labels = {} const labels = {}

View File

@@ -34,7 +34,7 @@ vi.mock('src/stores/Research/research.store', () => {
describe('Research update form', () => { describe('Research update form', () => {
describe('Invalid file warning', () => { describe('Invalid file warning', () => {
it('Does not appear when submitting only fileLink', async () => { it('Does not appear when submitting only fileLink', () => {
const formValues = FactoryResearchItemUpdate({ const formValues = FactoryResearchItemUpdate({
fileLink: 'www.filedonwload.test', fileLink: 'www.filedonwload.test',
}) })
@@ -46,7 +46,7 @@ describe('Research update form', () => {
).not.toBeInTheDocument() ).not.toBeInTheDocument()
}) })
it('Does not appear when submitting only files', async () => { it('Does not appear when submitting only files', () => {
// Arrange // Arrange
const formValues = FactoryResearchItemUpdate({ const formValues = FactoryResearchItemUpdate({
files: [new File(['test file content'], 'test-file.zip')], files: [new File(['test file content'], 'test-file.zip')],

View File

@@ -70,7 +70,7 @@ describe('Research Article', () => {
incrementViewCount: vi.fn(), incrementViewCount: vi.fn(),
} }
it('displays content statistics', async () => { it('displays content statistics', () => {
// Arrange // Arrange
const activeResearchItem = FactoryResearchItem({ const activeResearchItem = FactoryResearchItem({
collaborators: undefined, collaborators: undefined,
@@ -89,21 +89,23 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert // Assert
expect( waitFor(() => {
wrapper.getByText(`${activeResearchItem.total_views} views`), expect(
).toBeInTheDocument() wrapper.getByText(`${activeResearchItem.total_views} views`),
expect(wrapper.getByText('0 following')).toBeInTheDocument() ).toBeInTheDocument()
expect(wrapper.getByText('0 useful')).toBeInTheDocument() expect(wrapper.getByText('0 following')).toBeInTheDocument()
expect(wrapper.getByText('0 comments')).toBeInTheDocument() expect(wrapper.getByText('0 useful')).toBeInTheDocument()
expect(wrapper.getByText('1 step')).toBeInTheDocument() expect(wrapper.getByText('0 comments')).toBeInTheDocument()
expect(wrapper.getByText('1 step')).toBeInTheDocument()
})
}) })
it('does not display contributors when undefined', async () => { it('does not display contributors when undefined', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -114,7 +116,7 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
@@ -124,7 +126,7 @@ describe('Research Article', () => {
}).toThrow() }).toThrow()
}) })
it('displays contributors', async () => { it('displays contributors', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -135,18 +137,20 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert // Assert
expect(wrapper.getAllByText('With contributions from:')).toHaveLength(1) waitFor(() => {
expect(wrapper.getAllByText('example-username')).toHaveLength(2) expect(wrapper.getAllByText('With contributions from:')).toHaveLength(1)
expect(wrapper.getAllByText('another-example-username')).toHaveLength(2) expect(wrapper.getAllByText('example-username')).toHaveLength(2)
expect(wrapper.getAllByTestId('Username: known flag')).toHaveLength(4) expect(wrapper.getAllByText('another-example-username')).toHaveLength(2)
expect(wrapper.getAllByTestId('Username: known flag')).toHaveLength(4)
})
}) })
it('displays "Follow" button for non-subscriber', async () => { it('displays "Follow" button for non-subscriber', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -158,21 +162,24 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
const followButton = wrapper.getAllByTestId('follow-button')[0]
// Assert waitFor(() => {
expect(followButton).toBeInTheDocument() const followButton = wrapper.getAllByTestId('follow-button')[0]
expect(followButton).toHaveTextContent('Follow')
expect(followButton).not.toHaveTextContent('Following') // Assert
expect(followButton).toBeInTheDocument()
expect(followButton).toHaveTextContent('Follow')
expect(followButton).not.toHaveTextContent('Following')
})
}) })
it.todo('displays "Following" button for subscriber') it.todo('displays "Following" button for subscriber')
// TODO: Work out how to simulate store subscribe functionality // TODO: Work out how to simulate store subscribe functionality
// it('displays "Following" button for subscriber', async () => { // it('displays "Following" button for subscriber', () => {
// // Arrange // // Arrange
// ;(useResearchStore as Mock).mockReturnValue({ // ;(useResearchStore as Mock).mockReturnValue({
// ...mockResearchStore, // ...mockResearchStore,
@@ -185,7 +192,7 @@ describe('Research Article', () => {
// // Act // // Act
// let wrapper // let wrapper
// await act(async () => { // act( () => {
// wrapper = getWrapper() // wrapper = getWrapper()
// }) // })
// const followButton = wrapper.getAllByTestId('follow-button')[0] // const followButton = wrapper.getAllByTestId('follow-button')[0]
@@ -195,7 +202,7 @@ describe('Research Article', () => {
// }) // })
describe('Research Update', () => { describe('Research Update', () => {
it('displays contributors', async () => { it('displays contributors', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -229,21 +236,23 @@ describe('Research Article', () => {
// wait for Promise to resolve and state to update // wait for Promise to resolve and state to update
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert // Assert
expect(wrapper.getAllByText('With contributions from:')).toHaveLength(1) waitFor(() => {
expect(wrapper.getAllByText('example-username')).toHaveLength(2) expect(wrapper.getAllByText('With contributions from:')).toHaveLength(1)
expect(wrapper.getAllByText('another-example-username')).toHaveLength(2) expect(wrapper.getAllByText('example-username')).toHaveLength(2)
expect(wrapper.getAllByText('third-example-username')).toHaveLength(1) expect(wrapper.getAllByText('another-example-username')).toHaveLength(2)
expect(wrapper.queryByText('fourth-example-username')).toBeNull() expect(wrapper.getAllByText('third-example-username')).toHaveLength(1)
expect(wrapper.getAllByTestId('collaborator/creator')).toHaveLength(1) expect(wrapper.queryByText('fourth-example-username')).toBeNull()
expect(wrapper.getAllByTestId('Username: known flag')).toHaveLength(5) expect(wrapper.getAllByTestId('collaborator/creator')).toHaveLength(1)
expect(wrapper.getAllByTestId('Username: known flag')).toHaveLength(5)
})
}) })
it('does not show edit timestamp, when create displays the same value', async () => { it('does not show edit timestamp, when create displays the same value', () => {
const created = faker.date.past() const created = faker.date.past()
const modified = new Date(created) const modified = new Date(created)
modified.setHours(15) modified.setHours(15)
@@ -267,14 +276,14 @@ describe('Research Article', () => {
const wrapper = getWrapper() const wrapper = getWrapper()
// Assert // Assert
await waitFor(async () => { waitFor(() => {
expect(() => expect(() =>
wrapper.getAllByText(`edited ${formatDate(modified)}`), wrapper.getAllByText(`edited ${formatDate(modified)}`),
).toThrow() ).toThrow()
}) })
}) })
it('does show both created and edit timestamp, when different', async () => { it('does show both created and edit timestamp, when different', () => {
const modified = faker.date.future() const modified = faker.date.future()
const update = FactoryResearchItemUpdate({ const update = FactoryResearchItemUpdate({
_created: faker.date.past().toString(), _created: faker.date.past().toString(),
@@ -298,7 +307,7 @@ describe('Research Article', () => {
const wrapper = getWrapper() const wrapper = getWrapper()
// Assert // Assert
await waitFor(async () => { waitFor(() => {
expect(() => expect(() =>
wrapper.getAllByText(`edited ${formatDate(modified)}`), wrapper.getAllByText(`edited ${formatDate(modified)}`),
).not.toThrow() ).not.toThrow()
@@ -306,7 +315,7 @@ describe('Research Article', () => {
}) })
}) })
it('shows only published updates', async () => { it('shows only published updates', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -329,17 +338,19 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert // Assert
expect(wrapper.getByText('Research Update #1')).toBeInTheDocument() waitFor(() => {
expect(wrapper.queryByText('Research Update #2')).not.toBeInTheDocument() expect(wrapper.getByText('Research Update #1')).toBeInTheDocument()
expect(wrapper.queryByText('Research Update #2')).not.toBeInTheDocument()
})
}) })
describe('Breadcrumbs', () => { describe('Breadcrumbs', () => {
it('displays breadcrumbs with category', async () => { it('displays breadcrumbs with category', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -358,29 +369,31 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert: Check the breadcrumb items and chevrons // Assert: Check the breadcrumb items and chevrons
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') waitFor(() => {
expect(breadcrumbItems).toHaveLength(3) const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems[0]).toHaveTextContent('Research') expect(breadcrumbItems).toHaveLength(3)
expect(breadcrumbItems[1]).toHaveTextContent('Science') expect(breadcrumbItems[0]).toHaveTextContent('Research')
expect(breadcrumbItems[2]).toHaveTextContent('Innovative Study') expect(breadcrumbItems[1]).toHaveTextContent('Science')
expect(breadcrumbItems[2]).toHaveTextContent('Innovative Study')
// Assert: Check that the first two breadcrumb items contain links // Assert: Check that the first two breadcrumb items contain links
const firstLink = within(breadcrumbItems[0]).getByRole('link') const firstLink = within(breadcrumbItems[0]).getByRole('link')
const secondLink = within(breadcrumbItems[1]).getByRole('link') const secondLink = within(breadcrumbItems[1]).getByRole('link')
expect(firstLink).toBeInTheDocument() expect(firstLink).toBeInTheDocument()
expect(secondLink).toBeInTheDocument() expect(secondLink).toBeInTheDocument()
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(2) expect(chevrons).toHaveLength(2)
})
}) })
it('displays breadcrumbs without category', async () => { it('displays breadcrumbs without category', () => {
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -392,23 +405,25 @@ describe('Research Article', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = getWrapper() wrapper = getWrapper()
}) })
// Assert: Check the breadcrumb items and chevrons // Assert: Check the breadcrumb items and chevrons
const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem') waitFor(() => {
expect(breadcrumbItems).toHaveLength(2) const breadcrumbItems = wrapper.getAllByTestId('breadcrumbsItem')
expect(breadcrumbItems[0]).toHaveTextContent('Research') expect(breadcrumbItems).toHaveLength(2)
expect(breadcrumbItems[1]).toHaveTextContent('Innovative Study') expect(breadcrumbItems[0]).toHaveTextContent('Research')
expect(breadcrumbItems[1]).toHaveTextContent('Innovative Study')
// Assert: Check that the first breadcrumb item contains a link // Assert: Check that the first breadcrumb item contains a link
const firstLink = within(breadcrumbItems[0]).getByRole('link') const firstLink = within(breadcrumbItems[0]).getByRole('link')
expect(firstLink).toBeInTheDocument() expect(firstLink).toBeInTheDocument()
// Assert: Check for the correct number of chevrons // Assert: Check for the correct number of chevrons
const chevrons = wrapper.getAllByTestId('breadcrumbsChevron') const chevrons = wrapper.getAllByTestId('breadcrumbsChevron')
expect(chevrons).toHaveLength(1) expect(chevrons).toHaveLength(1)
})
}) })
}) })
}) })

View File

@@ -108,7 +108,7 @@ describe('research.routes', () => {
}) })
describe('/research/', () => { describe('/research/', () => {
it('renders the research listing', async () => { it('renders the research listing', () => {
const researchTitle = faker.lorem.words(3) const researchTitle = faker.lorem.words(3)
const researchSlug = faker.lorem.slug() const researchSlug = faker.lorem.slug()
@@ -132,7 +132,7 @@ describe('research.routes', () => {
const wrapper = renderFn('/research') const wrapper = renderFn('/research')
await vi.waitFor( vi.waitFor(
() => () =>
expect( expect(
wrapper.getByText(/Help out with Research & Development/), wrapper.getByText(/Help out with Research & Development/),
@@ -145,13 +145,13 @@ describe('research.routes', () => {
}) })
describe('/research/:slug', () => { describe('/research/:slug', () => {
it('renders an individual research article', async () => { it('renders an individual research article', () => {
let wrapper let wrapper
act(() => { act(() => {
wrapper = renderFn('/research/research-slug') wrapper = renderFn('/research/research-slug')
}) })
await vi.waitFor( vi.waitFor(
() => { () => {
expect(wrapper.queryByTestId('research-title')).toHaveTextContent( expect(wrapper.queryByTestId('research-title')).toHaveTextContent(
'Research article title', 'Research article title',
@@ -165,34 +165,34 @@ describe('research.routes', () => {
}) })
describe('/research/create', () => { describe('/research/create', () => {
it('rejects a request without a user present', async () => { it('rejects a request without a user present', () => {
mockActiveUser.userRoles = [] mockActiveUser.userRoles = []
let wrapper let wrapper
act(() => { act(() => {
wrapper = renderFn('/research/create') wrapper = renderFn('/research/create')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('rejects a logged in user missing required role', async () => { it('rejects a logged in user missing required role', () => {
let wrapper let wrapper
act(() => { act(() => {
wrapper = renderFn('/research/create') wrapper = renderFn('/research/create')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('accepts a logged in user with required role [research_creator]', async () => { it('accepts a logged in user with required role [research_creator]', () => {
let wrapper let wrapper
act(() => { act(() => {
mockActiveUser.userRoles = [UserRole.RESEARCH_CREATOR] mockActiveUser.userRoles = [UserRole.RESEARCH_CREATOR]
@@ -200,7 +200,7 @@ describe('research.routes', () => {
wrapper = renderFn('/research/create') wrapper = renderFn('/research/create')
}) })
await vi.waitFor( vi.waitFor(
() => { () => {
expect(wrapper.getByText(/start your research/i)).toBeInTheDocument() expect(wrapper.getByText(/start your research/i)).toBeInTheDocument()
}, },
@@ -210,14 +210,14 @@ describe('research.routes', () => {
) )
}) })
it('accepts a logged in user with required role [research_creator]', async () => { it('accepts a logged in user with required role [research_creator]', () => {
let wrapper let wrapper
act(() => { act(() => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
wrapper = renderFn('/research/create') wrapper = renderFn('/research/create')
}) })
await vi.waitFor( vi.waitFor(
() => { () => {
expect(wrapper.getByText(/start your research/i)).toBeInTheDocument() expect(wrapper.getByText(/start your research/i)).toBeInTheDocument()
}, },
@@ -229,7 +229,7 @@ describe('research.routes', () => {
}) })
describe('/research/:slug/edit', () => { describe('/research/:slug/edit', () => {
it('rejects a request without a user present', async () => { it('rejects a request without a user present', () => {
mockActiveUser.userRoles = [] mockActiveUser.userRoles = []
let wrapper let wrapper
@@ -237,14 +237,14 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/edit') wrapper = renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('accepts a logged in user with required role', async () => { it('accepts a logged in user with required role', () => {
let wrapper let wrapper
act(() => { act(() => {
mockActiveUser.userName = 'Jaasper' mockActiveUser.userName = 'Jaasper'
@@ -253,12 +253,12 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/edit') wrapper = renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByText(/edit your research/i)).toBeInTheDocument() expect(wrapper.getByText(/edit your research/i)).toBeInTheDocument()
}) })
}) })
it('rejects a logged in user with required role but not author of document', async () => { it('rejects a logged in user with required role but not author of document', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
// Arrange // Arrange
@@ -275,12 +275,12 @@ describe('research.routes', () => {
renderFn('/research/an-example/edit') renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(mockedUsedNavigate).toHaveBeenCalledWith('/research/an-example') expect(mockedUsedNavigate).toHaveBeenCalledWith('/research/an-example')
}) })
}) })
it('blocks a valid editor when document is locked by another user', async () => { it('blocks a valid editor when document is locked by another user', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -300,7 +300,7 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/edit') wrapper = renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText( wrapper.getByText(
'The research description is currently being edited by another editor.', 'The research description is currently being edited by another editor.',
@@ -309,7 +309,7 @@ describe('research.routes', () => {
}) })
}) })
it('accepts a user when document is mark locked by them', async () => { it('accepts a user when document is mark locked by them', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -329,12 +329,12 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/edit') wrapper = renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByText('Edit your Research')).toBeInTheDocument() expect(wrapper.getByText('Edit your Research')).toBeInTheDocument()
}) })
}) })
it('accepts a user with required role and contributor acccess', async () => { it('accepts a user with required role and contributor acccess', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -350,14 +350,14 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/edit') wrapper = renderFn('/research/an-example/edit')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByText(/edit your research/i)).toBeInTheDocument() expect(wrapper.getByText(/edit your research/i)).toBeInTheDocument()
}) })
}) })
}) })
describe('/research/:slug/new-update', () => { describe('/research/:slug/new-update', () => {
it('rejects a request without a user present', async () => { it('rejects a request without a user present', () => {
mockActiveUser.userRoles = [] mockActiveUser.userRoles = []
let wrapper let wrapper
@@ -365,41 +365,41 @@ describe('research.routes', () => {
wrapper = renderFn('/research/an-example/new-update') wrapper = renderFn('/research/an-example/new-update')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('accepts a logged in user with required role', async () => { it('accepts a logged in user with required role', () => {
let wrapper let wrapper
act(() => { act(() => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
wrapper = renderFn('/research/an-example/new-update') wrapper = renderFn('/research/an-example/new-update')
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByTestId('EditResearchUpdate')).toBeInTheDocument() expect(wrapper.getByTestId('EditResearchUpdate')).toBeInTheDocument()
}) })
}) })
}) })
describe('/research/:slug/edit-update/:id', () => { describe('/research/:slug/edit-update/:id', () => {
it('rejects a request without a user present', async () => { it('rejects a request without a user present', () => {
mockActiveUser.userRoles = [] mockActiveUser.userRoles = []
const wrapper = renderFn( const wrapper = renderFn(
'/research/an-example/edit-update/nested-research-update', '/research/an-example/edit-update/nested-research-update',
) )
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('accept logged in author present', async () => { it('accept logged in author present', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
// Arrange // Arrange
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
@@ -424,12 +424,12 @@ describe('research.routes', () => {
) )
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByTestId(/EditResearchUpdate/i)).toBeInTheDocument() expect(wrapper.getByTestId(/EditResearchUpdate/i)).toBeInTheDocument()
}) })
}) })
it('blocks valid author when document is locked', async () => { it('blocks valid author when document is locked', () => {
// Arrange // Arrange
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
@@ -455,7 +455,7 @@ describe('research.routes', () => {
'/research/an-example/edit-update/nested-research-update', '/research/an-example/edit-update/nested-research-update',
) )
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText( wrapper.getByText(
/This research update is currently being edited by another editor/, /This research update is currently being edited by another editor/,
@@ -464,7 +464,7 @@ describe('research.routes', () => {
}) })
}) })
it('accepts a user when document is mark locked by them', async () => { it('accepts a user when document is mark locked by them', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
;(useResearchStore as Mock).mockReturnValue({ ;(useResearchStore as Mock).mockReturnValue({
...mockResearchStore, ...mockResearchStore,
@@ -488,12 +488,12 @@ describe('research.routes', () => {
'/research/an-example/edit-update/nested-research-update', '/research/an-example/edit-update/nested-research-update',
) )
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByText('Edit your update')).toBeInTheDocument() expect(wrapper.getByText('Edit your update')).toBeInTheDocument()
}) })
}) })
it('rejects logged in user who is not author', async () => { it('rejects logged in user who is not author', () => {
mockActiveUser.userRoles = [] mockActiveUser.userRoles = []
let wrapper let wrapper
@@ -503,14 +503,14 @@ describe('research.routes', () => {
) )
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect( expect(
wrapper.getByText(/role required to access this page/), wrapper.getByText(/role required to access this page/),
).toBeInTheDocument() ).toBeInTheDocument()
}) })
}) })
it('accept logged in user who is collaborator', async () => { it('accept logged in user who is collaborator', () => {
mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR] mockActiveUser.userRoles = [UserRole.RESEARCH_EDITOR]
// Arrange // Arrange
@@ -535,7 +535,7 @@ describe('research.routes', () => {
) )
}) })
await vi.waitFor(() => { vi.waitFor(() => {
expect(wrapper.getByTestId(/EditResearchUpdate/i)).toBeInTheDocument() expect(wrapper.getByTestId(/EditResearchUpdate/i)).toBeInTheDocument()
}) })
}) })

View File

@@ -37,7 +37,7 @@ vi.mock('../../config/config', () => ({
})) }))
describe('research.search', () => { describe('research.search', () => {
it('searches for text', async () => { it('searches for text', () => {
// prepare // prepare
const words = ['test', 'text'] const words = ['test', 'text']
@@ -52,7 +52,7 @@ describe('research.search', () => {
) )
}) })
it('filters by category', async () => { it('filters by category', () => {
// prepare // prepare
const category = 'cat1' const category = 'cat1'
@@ -67,7 +67,7 @@ describe('research.search', () => {
) )
}) })
it('should not call orderBy if sorting by most relevant', async () => { it('should not call orderBy if sorting by most relevant', () => {
// act // act
exportedForTesting.createSearchQuery(['test'], '', 'MostRelevant', null) exportedForTesting.createSearchQuery(['test'], '', 'MostRelevant', null)
@@ -75,7 +75,7 @@ describe('research.search', () => {
expect(mockOrderBy).toHaveBeenCalledTimes(0) expect(mockOrderBy).toHaveBeenCalledTimes(0)
}) })
it('should call orderBy when sorting is not MostRelevant', async () => { it('should call orderBy when sorting is not MostRelevant', () => {
// act // act
exportedForTesting.createSearchQuery(['test'], '', 'Newest', null) exportedForTesting.createSearchQuery(['test'], '', 'Newest', null)
@@ -83,7 +83,7 @@ describe('research.search', () => {
expect(mockOrderBy).toHaveBeenLastCalledWith('_created', 'desc') expect(mockOrderBy).toHaveBeenLastCalledWith('_created', 'desc')
}) })
it('should filter by research status', async () => { it('should filter by research status', () => {
// act // act
exportedForTesting.createSearchQuery( exportedForTesting.createSearchQuery(
['test'], ['test'],
@@ -100,7 +100,7 @@ describe('research.search', () => {
) )
}) })
it('should limit results', async () => { it('should limit results', () => {
// prepare // prepare
const take = 12 const take = 12

View File

@@ -7,7 +7,7 @@ import type { IResearch, IUserPPDB } from 'src/models'
describe('Research Helpers', () => { describe('Research Helpers', () => {
describe('Research Update Status Filter', () => { describe('Research Update Status Filter', () => {
it('should not show item when deleted', async () => { it('should not show item when deleted', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { _createdBy: user._id } as IResearch.Item const item = { _createdBy: user._id } as IResearch.Item
@@ -20,7 +20,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(false) expect(show).toEqual(false)
}) })
it('should not show item when deleted and draft', async () => { it('should not show item when deleted and draft', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { _createdBy: user._id } as IResearch.Item const item = { _createdBy: user._id } as IResearch.Item
@@ -36,7 +36,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(false) expect(show).toEqual(false)
}) })
it('should not show when draft and not author', async () => { it('should not show when draft and not author', () => {
// prepare // prepare
const user = { _id: 'non-author' } as IUserPPDB const user = { _id: 'non-author' } as IUserPPDB
const item = { _createdBy: 'author' } as IResearch.Item const item = { _createdBy: 'author' } as IResearch.Item
@@ -49,7 +49,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(false) expect(show).toEqual(false)
}) })
it('should not show when draft and not authenticated', async () => { it('should not show when draft and not authenticated', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { _createdBy: user._id } as IResearch.Item const item = { _createdBy: user._id } as IResearch.Item
@@ -62,7 +62,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(false) expect(show).toEqual(false)
}) })
it('should show when not draft and not deleted', async () => { it('should show when not draft and not deleted', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { _createdBy: user._id } as IResearch.Item const item = { _createdBy: user._id } as IResearch.Item
@@ -77,7 +77,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(true) expect(show).toEqual(true)
}) })
it('should show when draft and current user is the author', async () => { it('should show when draft and current user is the author', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { _createdBy: user._id } as IResearch.Item const item = { _createdBy: user._id } as IResearch.Item
@@ -90,7 +90,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(true) expect(show).toEqual(true)
}) })
it('should show when draft and current user is a collaborator', async () => { it('should show when draft and current user is a collaborator', () => {
// prepare // prepare
const user = { _id: 'author' } as IUserPPDB const user = { _id: 'author' } as IUserPPDB
const item = { collaborators: [user._id] } as IResearch.Item const item = { collaborators: [user._id] } as IResearch.Item
@@ -103,7 +103,7 @@ describe('Research Helpers', () => {
expect(show).toEqual(true) expect(show).toEqual(true)
}) })
it('should show when draft and current user is an Admin', async () => { it('should show when draft and current user is an Admin', () => {
// prepare // prepare
const user = { _id: 'admin', userRoles: [UserRole.ADMIN] } as IUserPPDB const user = { _id: 'admin', userRoles: [UserRole.ADMIN] } as IUserPPDB
const item = {} as IResearch.Item const item = {} as IResearch.Item

View File

@@ -57,7 +57,7 @@ describe('UserContactForm', () => {
await screen.findByText(contact.successMessage) await screen.findByText(contact.successMessage)
}) })
it('renders nothing if not profile is not contactable', async () => { it('renders nothing if not profile is not contactable', () => {
const uncontactable = FactoryUser({ isContactableByPublic: false }) const uncontactable = FactoryUser({ isContactableByPublic: false })
const { container } = render( const { container } = render(

View File

@@ -64,7 +64,7 @@ describe('Impact', () => {
await screen.findByText('45 volunteers') await screen.findByText('45 volunteers')
await screen.findByText('23,000 Kg of plastic recycled') await screen.findByText('23,000 Kg of plastic recycled')
await screen.findByText('$ 54,000 revenue') await screen.findByText('$ 54,000 revenue')
const machineField = await screen.queryByText('13 machines built') const machineField = screen.queryByText('13 machines built')
expect(machineField).toBe(null) expect(machineField).toBe(null)
for (const year of IMPACT_YEARS) { for (const year of IMPACT_YEARS) {

View File

@@ -16,7 +16,7 @@ describe('ImpactField', () => {
await screen.findByText('23,000 Kg of plastic recycled') await screen.findByText('23,000 Kg of plastic recycled')
}) })
it('renders nothing when field is not set to be visible', async () => { it('renders nothing when field is not set to be visible', () => {
const field = { const field = {
id: 'plastic', id: 'plastic',
value: 3, value: 3,
@@ -28,7 +28,7 @@ describe('ImpactField', () => {
expect(container.innerHTML).toBe('') expect(container.innerHTML).toBe('')
}) })
it("renders nothing when field isn't found in question data", async () => { it("renders nothing when field isn't found in question data", () => {
const field = { const field = {
id: 'nothing', id: 'nothing',
value: 3, value: 3,

View File

@@ -6,7 +6,7 @@ import {
RouterProvider, RouterProvider,
} from 'react-router-dom' } from 'react-router-dom'
import { ThemeProvider } from '@emotion/react' import { ThemeProvider } from '@emotion/react'
import { act, render } from '@testing-library/react' import { act, render, waitFor } from '@testing-library/react'
import { Provider } from 'mobx-react' import { Provider } from 'mobx-react'
import { useCommonStores } from 'src/common/hooks/useCommonStores' import { useCommonStores } from 'src/common/hooks/useCommonStores'
import { FactoryUser } from 'src/test/factories/User' import { FactoryUser } from 'src/test/factories/User'
@@ -58,32 +58,36 @@ describe('User', () => {
vi.resetAllMocks() vi.resetAllMocks()
}) })
it('displays user page', async () => { it('displays user page', () => {
const user = FactoryUser() const user = FactoryUser()
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await getWrapper(user) wrapper = getWrapper(user)
}) })
// Assert // Assert
expect(wrapper.getByText(user.displayName)).toBeInTheDocument() waitFor(() => {
expect(wrapper.getByText(user.displayName)).toBeInTheDocument()
})
}) })
it('displays user not found page', async () => { it('displays user not found page', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await getWrapper(null, '/u/does-not-exist') wrapper = getWrapper(null, '/u/does-not-exist')
}) })
// Assert // Assert
expect(wrapper.getByText('User not found')).toBeInTheDocument() waitFor(() => {
expect(wrapper.getByText('User not found')).toBeInTheDocument()
})
}) })
describe('workspace', () => { describe('workspace', () => {
it('handles workspace with no images', async () => { it('handles workspace with no images', () => {
const user = FactoryUser({ const user = FactoryUser({
profileType: 'workspace', profileType: 'workspace',
coverImages: [], coverImages: [],
@@ -91,17 +95,19 @@ describe('User', () => {
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await getWrapper(user) wrapper = getWrapper(user)
}) })
// Assert // Assert
expect(wrapper.getByText('No images available.')).toBeInTheDocument() waitFor(() => {
expect(wrapper.getByText('No images available.')).toBeInTheDocument()
})
}) })
}) })
}) })
const getWrapper = async (user, url?) => { const getWrapper = (user, url?) => {
mockGetUserProfile.mockResolvedValue(user) mockGetUserProfile.mockResolvedValue(user)
const router = createMemoryRouter(createRoutesFromElements(UserRoutes), { const router = createMemoryRouter(createRoutesFromElements(UserRoutes), {

View File

@@ -7,7 +7,7 @@ import {
RouterProvider, RouterProvider,
} from 'react-router-dom' } from 'react-router-dom'
import { ThemeProvider } from '@emotion/react' import { ThemeProvider } from '@emotion/react'
import { act, render } from '@testing-library/react' import { act, render, waitFor } from '@testing-library/react'
import { Provider } from 'mobx-react' import { Provider } from 'mobx-react'
import { IModerationStatus } from 'oa-shared' import { IModerationStatus } from 'oa-shared'
import { useCommonStores } from 'src/common/hooks/useCommonStores' import { useCommonStores } from 'src/common/hooks/useCommonStores'
@@ -19,6 +19,8 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { SettingsPage } from './SettingsPage' import { SettingsPage } from './SettingsPage'
import type { IUserPPDB } from 'src/models'
const Theme = testingThemeStyles const Theme = testingThemeStyles
// eslint-disable-next-line prefer-const // eslint-disable-next-line prefer-const
@@ -67,81 +69,101 @@ describe('UserSettings', () => {
vi.resetAllMocks() vi.resetAllMocks()
}) })
it('displays user settings', async () => { it('displays user settings', () => {
mockUser = FactoryUser() mockUser = FactoryUser()
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
}) })
// Assert // Assert
expect(wrapper.getByText('Edit profile')) waitFor(() => {
expect(wrapper.getByText('Edit profile'))
})
}) })
it('displays one photo for member', async () => { it('displays one photo for member', () => {
mockUser = FactoryUser({ profileType: 'member' }) mockUser = FactoryUser({ profileType: 'member' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(1)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(1)
}) })
it('displays four photos for collection point', async () => { it('displays four photos for collection point', () => {
mockUser = FactoryUser({ profileType: 'collection-point' }) mockUser = FactoryUser({ profileType: 'collection-point' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
it('displays four photos for community builder', async () => { it('displays four photos for community builder', () => {
mockUser = FactoryUser({ profileType: 'community-builder' }) mockUser = FactoryUser({ profileType: 'community-builder' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
it('displays four photos for machine builder', async () => { it('displays four photos for machine builder', () => {
mockUser = FactoryUser({ profileType: 'machine-builder' }) mockUser = FactoryUser({ profileType: 'machine-builder' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
it('displays four photos for space', async () => { it('displays four photos for space', () => {
mockUser = FactoryUser({ profileType: 'space' }) mockUser = FactoryUser({ profileType: 'space' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
it('displays four photos for workspace', async () => { it('displays four photos for workspace', () => {
mockUser = FactoryUser({ profileType: 'workspace' }) mockUser = FactoryUser({ profileType: 'workspace' })
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
expect(wrapper.getAllByTestId('cover-image')).toHaveLength(4)
}) })
describe('map pin', () => { describe('map pin', () => {
it('displays moderation comments to user', async () => { it('displays moderation comments to user', () => {
mockUser = FactoryUser({ profileType: 'workspace' }) mockUser = FactoryUser({ profileType: 'workspace' })
mockGetPin.mockResolvedValue( mockGetPin.mockResolvedValue(
FactoryMapPin({ FactoryMapPin({
@@ -151,13 +173,16 @@ describe('UserSettings', () => {
) )
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
})
waitFor(() => {
expect(wrapper.getByText('Moderator comment')).toBeInTheDocument()
}) })
expect(wrapper.getByText('Moderator comment')).toBeInTheDocument()
}) })
it('does not show moderation comments for approved pin', async () => { it('does not show moderation comments for approved pin', () => {
mockUser = FactoryUser({ profileType: 'workspace' }) mockUser = FactoryUser({ profileType: 'workspace' })
mockGetPin.mockResolvedValue( mockGetPin.mockResolvedValue(
FactoryMapPin({ FactoryMapPin({
@@ -167,8 +192,8 @@ describe('UserSettings', () => {
) )
// Act // Act
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser) wrapper = Wrapper(mockUser)
}) })
expect(() => wrapper.getByText('Moderator comment')).toThrow() expect(() => wrapper.getByText('Moderator comment')).toThrow()
@@ -178,7 +203,7 @@ describe('UserSettings', () => {
const scrollIntoViewMock = vi.fn() const scrollIntoViewMock = vi.fn()
window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock
it('expands and scrolls to impact section if a #impact_year hash is provided and year is valid', async () => { it('expands and scrolls to impact section if a #impact_year hash is provided and year is valid', () => {
mockUser = FactoryUser({ mockUser = FactoryUser({
profileType: 'workspace', profileType: 'workspace',
}) })
@@ -187,14 +212,15 @@ describe('UserSettings', () => {
const { expandClose } = buttons.impact const { expandClose } = buttons.impact
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser, impactHash) wrapper = Wrapper(mockUser, impactHash)
})
waitFor(() => {
expect(wrapper.getByText(expandClose)).toBeInTheDocument()
expect(scrollIntoViewMock).toBeCalled()
}) })
expect(wrapper.getByText(expandClose)).toBeInTheDocument()
expect(scrollIntoViewMock).toBeCalled()
}) })
it('does not expand impact section if hash syntax is not correct', async () => { it('does not expand impact section if hash syntax is not correct', () => {
mockUser = FactoryUser({ mockUser = FactoryUser({
profileType: 'workspace', profileType: 'workspace',
}) })
@@ -203,15 +229,17 @@ describe('UserSettings', () => {
const { expandOpen } = buttons.impact const { expandOpen } = buttons.impact
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser, impactHash) wrapper = Wrapper(mockUser, impactHash)
}) })
expect(wrapper.getByText(expandOpen)).toBeInTheDocument() waitFor(() => {
expect(scrollIntoViewMock).not.toBeCalled() expect(wrapper.getByText(expandOpen)).toBeInTheDocument()
expect(scrollIntoViewMock).not.toBeCalled()
})
}) })
it('does not expand impact section if no impact hash is provided', async () => { it('does not expand impact section if no impact hash is provided', () => {
mockUser = FactoryUser({ mockUser = FactoryUser({
profileType: 'workspace', profileType: 'workspace',
}) })
@@ -219,17 +247,19 @@ describe('UserSettings', () => {
const { expandOpen } = buttons.impact const { expandOpen } = buttons.impact
let wrapper let wrapper
await act(async () => { act(() => {
wrapper = await Wrapper(mockUser, impactHash) wrapper = Wrapper(mockUser, impactHash)
}) })
expect(wrapper.getByText(expandOpen)).toBeInTheDocument() waitFor(() => {
expect(scrollIntoViewMock).not.toBeCalled() expect(wrapper.getByText(expandOpen)).toBeInTheDocument()
expect(scrollIntoViewMock).not.toBeCalled()
})
}) })
}) })
}) })
const Wrapper = async (user, routerInitialEntry?) => { const Wrapper = (user: IUserPPDB, routerInitialEntry?: string) => {
if (routerInitialEntry !== undefined) { if (routerInitialEntry !== undefined) {
// impact section is only displayed if isPreciousPlastic() is true // impact section is only displayed if isPreciousPlastic() is true
window.localStorage.setItem('platformTheme', 'precious-plastic') window.localStorage.setItem('platformTheme', 'precious-plastic')

View File

@@ -13,7 +13,7 @@ const supportedProfileTypes = getSupportedProfileTypes().map(
) )
describe('Focus', () => { describe('Focus', () => {
it('render focus section if more than one activity available', async () => { it('render focus section if more than one activity available', () => {
const badges = supportedProfileTypes.reduce( const badges = supportedProfileTypes.reduce(
(a, v) => ({ (a, v) => ({
...a, ...a,
@@ -36,7 +36,7 @@ describe('Focus', () => {
expect(screen.queryByText(headings.focus)).toBeInTheDocument() expect(screen.queryByText(headings.focus)).toBeInTheDocument()
}) })
it('does not render focus section if less than two activities available', async () => { it('does not render focus section if less than two activities available', () => {
const badges = { const badges = {
[supportedProfileTypes[0]]: { [supportedProfileTypes[0]]: {
lowDetail: '', lowDetail: '',

View File

@@ -122,8 +122,8 @@ describe('PatreonIntegration', () => {
expect(screen.getByText(REMOVE_BUTTON_TEXT)).toBeInTheDocument() expect(screen.getByText(REMOVE_BUTTON_TEXT)).toBeInTheDocument()
}) })
it('calls removePatreonConnection when "Remove Connection" button is clicked', async () => { it('calls removePatreonConnection when "Remove Connection" button is clicked', () => {
await act(async () => { act(() => {
fireEvent.click(screen.getByText(REMOVE_BUTTON_TEXT)) fireEvent.click(screen.getByText(REMOVE_BUTTON_TEXT))
}) })
expect(mockRemovePatreonConnection).toHaveBeenCalledWith( expect(mockRemovePatreonConnection).toHaveBeenCalledWith(

View File

@@ -41,7 +41,7 @@ describe('SettingsErrors', () => {
}) })
}) })
it('renders nothing when not visible', async () => { it('renders nothing when not visible', () => {
const errors = { const errors = {
title: 'Make sure this field is filled correctly', title: 'Make sure this field is filled correctly',
} }

View File

@@ -13,7 +13,7 @@ import { DiscussionStore } from './discussions.store'
import type { IDiscussion, IUserPPDB } from 'src/models' import type { IDiscussion, IUserPPDB } from 'src/models'
import type { IRootStore } from '../RootStore' import type { IRootStore } from '../RootStore'
const factory = async ( const factory = (
discussions: IDiscussion[] = [FactoryDiscussion({})], discussions: IDiscussion[] = [FactoryDiscussion({})],
activeUser: IUserPPDB = FactoryUser(), activeUser: IUserPPDB = FactoryUser(),
) => { ) => {
@@ -70,7 +70,7 @@ describe('discussion.store', () => {
it('fetches a discussion by sourceId', async () => { it('fetches a discussion by sourceId', async () => {
const fakeSourceId = faker.internet.password() const fakeSourceId = faker.internet.password()
const fakePrimaryContentId = faker.internet.password() const fakePrimaryContentId = faker.internet.password()
const { store, getWhereFn } = await factory([ const { store, getWhereFn } = factory([
FactoryDiscussion({ sourceId: fakeSourceId }), FactoryDiscussion({ sourceId: fakeSourceId }),
]) ])
@@ -85,7 +85,7 @@ describe('discussion.store', () => {
}) })
it('creates a discussion if one does not exist', async () => { it('creates a discussion if one does not exist', async () => {
const { store, getWhereFn, setFn } = await factory() const { store, getWhereFn, setFn } = factory()
getWhereFn.mockReturnValueOnce([]) getWhereFn.mockReturnValueOnce([])
@@ -109,7 +109,7 @@ describe('discussion.store', () => {
describe('uploadDiscussion', () => { describe('uploadDiscussion', () => {
it('creates a new discussion with sourceId and sourceType provided', async () => { it('creates a new discussion with sourceId and sourceType provided', async () => {
const { store, discussionItem, setFn } = await factory() const { store, discussionItem, setFn } = factory()
await store.uploadDiscussion( await store.uploadDiscussion(
discussionItem.sourceId, discussionItem.sourceId,
@@ -126,7 +126,7 @@ describe('discussion.store', () => {
describe('addComment', () => { describe('addComment', () => {
it('adds a new comment for questions', async () => { it('adds a new comment for questions', async () => {
const { store, discussionItem, setFn, getFn } = await factory() const { store, discussionItem, setFn, getFn } = factory()
//Act //Act
await store.addComment(discussionItem, 'New comment') await store.addComment(discussionItem, 'New comment')
@@ -151,7 +151,7 @@ describe('discussion.store', () => {
}) })
it('adds a reply to a comment', async () => { it('adds a reply to a comment', async () => {
const { store, discussionItem, setFn } = await factory([ const { store, discussionItem, setFn } = factory([
FactoryDiscussion({ FactoryDiscussion({
comments: [FactoryDiscussionComment({ text: 'New comment' })], comments: [FactoryDiscussionComment({ text: 'New comment' })],
}), }),
@@ -186,8 +186,8 @@ describe('discussion.store', () => {
) )
}) })
it('handles error fetching discussion', async () => { it('handles error fetching discussion', () => {
const { store, discussionItem, setFn, getFn } = await factory() const { store, discussionItem, setFn, getFn } = factory()
getFn.mockReturnValue(null) getFn.mockReturnValue(null)
//Act //Act
@@ -202,7 +202,7 @@ describe('discussion.store', () => {
describe('editComent', () => { describe('editComent', () => {
it('allows author to make changes comment', async () => { it('allows author to make changes comment', async () => {
const { store, discussionItem, setFn } = await factory( const { store, discussionItem, setFn } = factory(
[ [
FactoryDiscussion({ FactoryDiscussion({
comments: [ comments: [
@@ -238,7 +238,7 @@ describe('discussion.store', () => {
}) })
it('allows admin to make changes comment', async () => { it('allows admin to make changes comment', async () => {
const { store, discussionItem, setFn } = await factory( const { store, discussionItem, setFn } = factory(
[ [
FactoryDiscussion({ FactoryDiscussion({
comments: [ comments: [
@@ -274,8 +274,8 @@ describe('discussion.store', () => {
) )
}) })
it('throws an error for a different user', async () => { it('throws an error for a different user', () => {
const { store, discussionItem, setFn } = await factory([ const { store, discussionItem, setFn } = factory([
FactoryDiscussion({ FactoryDiscussion({
comments: [ comments: [
FactoryDiscussionComment({ FactoryDiscussionComment({
@@ -303,7 +303,7 @@ describe('discussion.store', () => {
_creatorId: 'fake-user', _creatorId: 'fake-user',
text: 'New comment', text: 'New comment',
}) })
const { store, setFn, discussionItem } = await factory( const { store, setFn, discussionItem } = factory(
[FactoryDiscussion({ comments: [comment] })], [FactoryDiscussion({ comments: [comment] })],
FactoryUser({ _id: 'fake-user' }), FactoryUser({ _id: 'fake-user' }),
) )
@@ -324,7 +324,7 @@ describe('discussion.store', () => {
_creatorId: 'not-admin-user', _creatorId: 'not-admin-user',
text: 'New comment', text: 'New comment',
}) })
const { store, setFn, discussionItem } = await factory( const { store, setFn, discussionItem } = factory(
[FactoryDiscussion({ comments: [comment] })], [FactoryDiscussion({ comments: [comment] })],
FactoryUser({ FactoryUser({
_id: 'admin-user', _id: 'admin-user',
@@ -340,8 +340,8 @@ describe('discussion.store', () => {
expect(setFn.mock.calls[0][0].comments[0]._deleted).toEqual(true) expect(setFn.mock.calls[0][0].comments[0]._deleted).toEqual(true)
}) })
it('throws an error for a different user', async () => { it('throws an error for a different user', () => {
const { store, discussionItem, setFn } = await factory([ const { store, discussionItem, setFn } = factory([
FactoryDiscussion({ FactoryDiscussion({
comments: [ comments: [
FactoryDiscussionComment({ FactoryDiscussionComment({

View File

@@ -23,7 +23,7 @@ vi.mock('../common/toggleDocUsefulByUser', () => ({
toggleDocUsefulByUser: () => mockToggleDocUsefulByUser(), toggleDocUsefulByUser: () => mockToggleDocUsefulByUser(),
})) }))
const factory = async () => { const factory = () => {
const store = new QuestionStore({} as IRootStore) const store = new QuestionStore({} as IRootStore)
store.isTitleThatReusesSlug = vi.fn().mockResolvedValue(false) store.isTitleThatReusesSlug = vi.fn().mockResolvedValue(false)
@@ -64,7 +64,7 @@ const factory = async () => {
describe('question.store', () => { describe('question.store', () => {
describe('upsertQuestion', () => { describe('upsertQuestion', () => {
it('assigns _createdBy', async () => { it('assigns _createdBy', async () => {
const { store, setFn } = await factory() const { store, setFn } = factory()
const newQuestion = FactoryQuestionItem({ const newQuestion = FactoryQuestionItem({
title: 'So what is plastic?', title: 'So what is plastic?',
_createdBy: undefined, _createdBy: undefined,
@@ -83,7 +83,7 @@ describe('question.store', () => {
describe('fetchQuestionBySlug', () => { describe('fetchQuestionBySlug', () => {
it('handles empty query response', async () => { it('handles empty query response', async () => {
const { store } = await factory() const { store } = factory()
const newQuestion = FactoryQuestionItem({ const newQuestion = FactoryQuestionItem({
title: 'How do you survive living in a tent?', title: 'How do you survive living in a tent?',
}) })
@@ -93,7 +93,7 @@ describe('question.store', () => {
}) })
it('returns a valid response', async () => { it('returns a valid response', async () => {
const { store, getWhereFn } = await factory() const { store, getWhereFn } = factory()
const newQuestion = FactoryQuestionItem({ const newQuestion = FactoryQuestionItem({
title: 'Question title', title: 'Question title',
}) })
@@ -108,7 +108,7 @@ describe('question.store', () => {
}) })
it('returns a valid response when a previous slug', async () => { it('returns a valid response when a previous slug', async () => {
const { store, getWhereFn } = await factory() const { store, getWhereFn } = factory()
const newQuestion = FactoryQuestionItem({ const newQuestion = FactoryQuestionItem({
title: 'Can I run a shredder at home?', title: 'Can I run a shredder at home?',
previousSlugs: ['shredder-at-home'], previousSlugs: ['shredder-at-home'],
@@ -125,7 +125,7 @@ describe('question.store', () => {
describe('incrementViews', () => { describe('incrementViews', () => {
it('increments views by one', async () => { it('increments views by one', async () => {
const { store, updateFn } = await factory() const { store, updateFn } = factory()
const question = FactoryQuestionItem({ const question = FactoryQuestionItem({
title: 'which trees to cut down', title: 'which trees to cut down',
@@ -149,7 +149,7 @@ describe('question.store', () => {
describe('toggleSubscriberStatusByUserName', () => { describe('toggleSubscriberStatusByUserName', () => {
it('calls the toggle subscriber function', async () => { it('calls the toggle subscriber function', async () => {
const { store } = await factory() const { store } = factory()
store.activeQuestionItem = FactoryQuestionItem() store.activeQuestionItem = FactoryQuestionItem()
await store.toggleSubscriberStatusByUserName() await store.toggleSubscriberStatusByUserName()
@@ -160,7 +160,7 @@ describe('question.store', () => {
describe('toggleUsefulByUser', () => { describe('toggleUsefulByUser', () => {
it('calls the toogle voted for function', async () => { it('calls the toogle voted for function', async () => {
const { store } = await factory() const { store } = factory()
store.activeQuestionItem = FactoryQuestionItem() store.activeQuestionItem = FactoryQuestionItem()
await store.toggleUsefulByUser() await store.toggleUsefulByUser()

View File

@@ -32,10 +32,10 @@ vi.mock('firebase/firestore', () => ({
increment: (value) => mockIncrement(value), increment: (value) => mockIncrement(value),
})) }))
const factoryResearchItem = async (researchItemOverloads: any = {}, ...rest) => const factoryResearchItem = (researchItemOverloads: any = {}, ...rest) =>
factory(FactoryResearchItem, researchItemOverloads, ...rest) factory(FactoryResearchItem, researchItemOverloads, ...rest)
const factoryResearchItemFormInput = async ( const factoryResearchItemFormInput = (
researchItemOverloads: any = {}, researchItemOverloads: any = {},
...rest ...rest
) => factory(FactoryResearchItemFormInput, researchItemOverloads, ...rest) ) => factory(FactoryResearchItemFormInput, researchItemOverloads, ...rest)

View File

@@ -65,7 +65,7 @@ describe('triggerNotification', () => {
) )
}) })
it('throws error when invalid user passed', async () => { it('throws error when invalid user passed', () => {
// Act // Act
expect( expect(
store.triggerNotification( store.triggerNotification(
@@ -93,15 +93,15 @@ describe('notifications.store', () => {
] ]
store.userStore.user.notifications = FactoryNotificationSample() store.userStore.user.notifications = FactoryNotificationSample()
}) })
it('loads user with notifications', async () => { it('loads user with notifications', () => {
const notifications = store.userStore.user?.notifications const notifications = store.userStore.user?.notifications
expect(notifications).toHaveLength(6) expect(notifications).toHaveLength(6)
}) })
it('gets unnotified notifications', async () => { it('gets unnotified notifications', () => {
const unnotified = store.getUnnotifiedNotifications() const unnotified = store.getUnnotifiedNotifications()
expect(unnotified).toHaveLength(2) expect(unnotified).toHaveLength(2)
}) })
it('gets unread notifications', async () => { it('gets unread notifications', () => {
const unread = store.getUnreadNotifications() const unread = store.getUnreadNotifications()
expect(unread).toHaveLength(3) expect(unread).toHaveLength(3)
}) })