mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-29 02:44:28 -05:00
refactor(tests): add test utils for mocking common things
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
b3fb1bbf30
commit
ad80b444ff
16 changed files with 186 additions and 117 deletions
|
@ -3,14 +3,14 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import * as UseApplicationStateModule from '../../../../../hooks/common/use-application-state'
|
|
||||||
import type { ApplicationState } from '../../../../../redux/application-state'
|
|
||||||
import { mockI18n } from '../../../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../../../test-utils/mock-i18n'
|
||||||
import { EditorAppBar } from './editor-app-bar'
|
import { EditorAppBar } from './editor-app-bar'
|
||||||
import type { NoteGroupPermissionEntry, NoteUserPermissionEntry } from '@hedgedoc/commons'
|
import type { NoteGroupPermissionEntry, NoteUserPermissionEntry } from '@hedgedoc/commons'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import type { PropsWithChildren } from 'react'
|
import type { PropsWithChildren } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { mockAppState } from '../../../../../test-utils/mock-app-state'
|
||||||
|
import type { LoginUserInfo } from '../../../../../api/me/types'
|
||||||
|
|
||||||
jest.mock('../../../../../components/layout/app-bar/base-app-bar', () => ({
|
jest.mock('../../../../../components/layout/app-bar/base-app-bar', () => ({
|
||||||
__esModule: true,
|
__esModule: true,
|
||||||
|
@ -40,7 +40,7 @@ const mockedCommonAppState = {
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
username: 'test'
|
username: 'test'
|
||||||
}
|
} as LoginUserInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('app bar', () => {
|
describe('app bar', () => {
|
||||||
|
@ -48,40 +48,34 @@ describe('app bar', () => {
|
||||||
afterAll(() => jest.restoreAllMocks())
|
afterAll(() => jest.restoreAllMocks())
|
||||||
|
|
||||||
it('contains note title when editor is synced', () => {
|
it('contains note title when editor is synced', () => {
|
||||||
jest.spyOn(UseApplicationStateModule, 'useApplicationState').mockImplementation((fn) => {
|
mockAppState({
|
||||||
return fn({
|
...mockedCommonAppState,
|
||||||
...mockedCommonAppState,
|
realtimeStatus: {
|
||||||
realtimeStatus: {
|
isSynced: true
|
||||||
isSynced: true
|
}
|
||||||
}
|
|
||||||
} as ApplicationState)
|
|
||||||
})
|
})
|
||||||
const view = render(<EditorAppBar />)
|
const view = render(<EditorAppBar />)
|
||||||
expect(view.container).toMatchSnapshot()
|
expect(view.container).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('contains alert when editor is not synced', () => {
|
it('contains alert when editor is not synced', () => {
|
||||||
jest.spyOn(UseApplicationStateModule, 'useApplicationState').mockImplementation((fn) => {
|
mockAppState({
|
||||||
return fn({
|
...mockedCommonAppState,
|
||||||
...mockedCommonAppState,
|
realtimeStatus: {
|
||||||
realtimeStatus: {
|
isSynced: false
|
||||||
isSynced: false
|
}
|
||||||
}
|
|
||||||
} as ApplicationState)
|
|
||||||
})
|
})
|
||||||
const view = render(<EditorAppBar />)
|
const view = render(<EditorAppBar />)
|
||||||
expect(view.container).toMatchSnapshot()
|
expect(view.container).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('contains note title and read-only marker when having only read permissions', () => {
|
it('contains note title and read-only marker when having only read permissions', () => {
|
||||||
jest.spyOn(UseApplicationStateModule, 'useApplicationState').mockImplementation((fn) => {
|
mockAppState({
|
||||||
return fn({
|
...mockedCommonAppState,
|
||||||
...mockedCommonAppState,
|
realtimeStatus: {
|
||||||
realtimeStatus: {
|
isSynced: true
|
||||||
isSynced: true
|
},
|
||||||
},
|
user: null
|
||||||
user: null
|
|
||||||
} as ApplicationState)
|
|
||||||
})
|
})
|
||||||
const view = render(<EditorAppBar />)
|
const view = render(<EditorAppBar />)
|
||||||
expect(view.container).toMatchSnapshot()
|
expect(view.container).toMatchSnapshot()
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import { mockI18n } from '../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../test-utils/mock-i18n'
|
||||||
import { mockNoteOwnership } from '../../../test-utils/note-ownership'
|
import { mockNotePermissions } from '../../../test-utils/mock-note-permissions'
|
||||||
import { DeletionModal } from './deletion-modal'
|
import { DeletionModal } from './deletion-modal'
|
||||||
import { render, screen } from '@testing-library/react'
|
import { render, screen } from '@testing-library/react'
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ describe('DeletionModal', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders correctly with deletionButtonI18nKey', async () => {
|
it('renders correctly with deletionButtonI18nKey', async () => {
|
||||||
mockNoteOwnership('test', 'test')
|
mockNotePermissions('test', 'test')
|
||||||
const onConfirm = jest.fn()
|
const onConfirm = jest.fn()
|
||||||
render(
|
render(
|
||||||
<DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}>
|
<DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}>
|
||||||
|
@ -31,7 +31,7 @@ describe('DeletionModal', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('disables deletion when user is not owner', async () => {
|
it('disables deletion when user is not owner', async () => {
|
||||||
mockNoteOwnership('test2', 'test')
|
mockNotePermissions('test2', 'test')
|
||||||
const onConfirm = jest.fn()
|
const onConfirm = jest.fn()
|
||||||
render(
|
render(
|
||||||
<DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}>
|
<DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}>
|
|
@ -4,13 +4,12 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import type { LoginUserInfo } from '../../../../api/me/types'
|
import type { LoginUserInfo } from '../../../../api/me/types'
|
||||||
import * as UseApplicationStateModule from '../../../../hooks/common/use-application-state'
|
|
||||||
import type { ApplicationState } from '../../../../redux/application-state'
|
|
||||||
import { useDisconnectOnUserLoginStatusChange } from './use-disconnect-on-user-login-status-change'
|
import { useDisconnectOnUserLoginStatusChange } from './use-disconnect-on-user-login-status-change'
|
||||||
import type { MessageTransporter } from '@hedgedoc/commons'
|
import type { MessageTransporter } from '@hedgedoc/commons'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import React, { Fragment } from 'react'
|
import React, { Fragment } from 'react'
|
||||||
import { Mock } from 'ts-mockery'
|
import { Mock } from 'ts-mockery'
|
||||||
|
import { mockAppState } from '../../../../test-utils/mock-app-state'
|
||||||
|
|
||||||
jest.mock('../../../../hooks/common/use-application-state')
|
jest.mock('../../../../hooks/common/use-application-state')
|
||||||
|
|
||||||
|
@ -21,11 +20,9 @@ describe('use logout on user change', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockUseApplicationState = (userLoggedIn: boolean) => {
|
const mockUseApplicationState = (userLoggedIn: boolean) => {
|
||||||
jest
|
mockAppState({
|
||||||
.spyOn(UseApplicationStateModule, 'useApplicationState')
|
user: userLoggedIn ? Mock.of<LoginUserInfo>({}) : null
|
||||||
.mockImplementation((fn) =>
|
})
|
||||||
fn(Mock.of<ApplicationState>({ user: userLoggedIn ? Mock.of<LoginUserInfo>({}) : null }))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let disconnectCallback: jest.Mock
|
let disconnectCallback: jest.Mock
|
||||||
|
|
|
@ -7,12 +7,12 @@ import * as AliasModule from '../../../../../../api/alias'
|
||||||
import * as NoteDetailsReduxModule from '../../../../../../redux/note-details/methods'
|
import * as NoteDetailsReduxModule from '../../../../../../redux/note-details/methods'
|
||||||
import type { NoteDetails } from '../../../../../../redux/note-details/types/note-details'
|
import type { NoteDetails } from '../../../../../../redux/note-details/types/note-details'
|
||||||
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
||||||
import { mockNoteOwnership } from '../../../../../../test-utils/note-ownership'
|
import { mockNotePermissions } from '../../../../../../test-utils/mock-note-permissions'
|
||||||
import * as useUiNotificationsModule from '../../../../../notifications/ui-notification-boundary'
|
|
||||||
import { AliasesAddForm } from './aliases-add-form'
|
import { AliasesAddForm } from './aliases-add-form'
|
||||||
import { act, render, screen } from '@testing-library/react'
|
import { act, render, screen } from '@testing-library/react'
|
||||||
import testEvent from '@testing-library/user-event'
|
import testEvent from '@testing-library/user-event'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
|
||||||
|
|
||||||
jest.mock('../../../../../../api/alias')
|
jest.mock('../../../../../../api/alias')
|
||||||
jest.mock('../../../../../../redux/note-details/methods')
|
jest.mock('../../../../../../redux/note-details/methods')
|
||||||
|
@ -24,14 +24,10 @@ const addPromise = Promise.resolve({ name: 'mock', primaryAlias: true, noteId: '
|
||||||
describe('AliasesAddForm', () => {
|
describe('AliasesAddForm', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mockI18n()
|
await mockI18n()
|
||||||
|
mockUiNotifications()
|
||||||
jest.spyOn(AliasModule, 'addAlias').mockImplementation(() => addPromise)
|
jest.spyOn(AliasModule, 'addAlias').mockImplementation(() => addPromise)
|
||||||
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
|
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
|
||||||
jest.spyOn(useUiNotificationsModule, 'useUiNotifications').mockReturnValue({
|
mockNotePermissions('test', 'test', undefined, { noteDetails: { id: 'mock-note' } as NoteDetails })
|
||||||
showErrorNotification: jest.fn(),
|
|
||||||
dismissNotification: jest.fn(),
|
|
||||||
dispatchUiNotification: jest.fn()
|
|
||||||
})
|
|
||||||
mockNoteOwnership('test', 'test', { noteDetails: { id: 'mock-note' } as NoteDetails })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
|
|
@ -7,16 +7,15 @@ import * as AliasModule from '../../../../../../api/alias'
|
||||||
import type { Alias } from '../../../../../../api/alias/types'
|
import type { Alias } from '../../../../../../api/alias/types'
|
||||||
import * as NoteDetailsReduxModule from '../../../../../../redux/note-details/methods'
|
import * as NoteDetailsReduxModule from '../../../../../../redux/note-details/methods'
|
||||||
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
||||||
import { mockNoteOwnership } from '../../../../../../test-utils/note-ownership'
|
import { mockNotePermissions } from '../../../../../../test-utils/mock-note-permissions'
|
||||||
import * as useUiNotificationsModule from '../../../../../notifications/ui-notification-boundary'
|
|
||||||
import { AliasesListEntry } from './aliases-list-entry'
|
import { AliasesListEntry } from './aliases-list-entry'
|
||||||
import { act, render, screen } from '@testing-library/react'
|
import { act, render, screen } from '@testing-library/react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
|
||||||
|
|
||||||
jest.mock('../../../../../../api/alias')
|
jest.mock('../../../../../../api/alias')
|
||||||
jest.mock('../../../../../../redux/note-details/methods')
|
jest.mock('../../../../../../redux/note-details/methods')
|
||||||
jest.mock('../../../../../notifications/ui-notification-boundary')
|
jest.mock('../../../../../notifications/ui-notification-boundary')
|
||||||
// This needs to be mocked here in addition to note-ownership.ts, because jest doesn't work otherwise
|
|
||||||
jest.mock('../../../../../../hooks/common/use-application-state')
|
jest.mock('../../../../../../hooks/common/use-application-state')
|
||||||
|
|
||||||
const deletePromise = Promise.resolve()
|
const deletePromise = Promise.resolve()
|
||||||
|
@ -25,14 +24,10 @@ const markAsPrimaryPromise = Promise.resolve({ name: 'mock', primaryAlias: true,
|
||||||
describe('AliasesListEntry', () => {
|
describe('AliasesListEntry', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mockI18n()
|
await mockI18n()
|
||||||
|
mockUiNotifications()
|
||||||
jest.spyOn(AliasModule, 'deleteAlias').mockImplementation(() => deletePromise)
|
jest.spyOn(AliasModule, 'deleteAlias').mockImplementation(() => deletePromise)
|
||||||
jest.spyOn(AliasModule, 'markAliasAsPrimary').mockImplementation(() => markAsPrimaryPromise)
|
jest.spyOn(AliasModule, 'markAliasAsPrimary').mockImplementation(() => markAsPrimaryPromise)
|
||||||
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
|
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
|
||||||
jest.spyOn(useUiNotificationsModule, 'useUiNotifications').mockReturnValue({
|
|
||||||
showErrorNotification: jest.fn(),
|
|
||||||
dismissNotification: jest.fn(),
|
|
||||||
dispatchUiNotification: jest.fn()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -41,7 +36,7 @@ describe('AliasesListEntry', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders an AliasesListEntry that is primary', async () => {
|
it('renders an AliasesListEntry that is primary', async () => {
|
||||||
mockNoteOwnership('test', 'test')
|
mockNotePermissions('test', 'test')
|
||||||
const testAlias: Alias = {
|
const testAlias: Alias = {
|
||||||
name: 'test-primary',
|
name: 'test-primary',
|
||||||
primaryAlias: true,
|
primaryAlias: true,
|
||||||
|
@ -59,7 +54,7 @@ describe('AliasesListEntry', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("disables button in AliasesListEntry if it's primary", () => {
|
it("disables button in AliasesListEntry if it's primary", () => {
|
||||||
mockNoteOwnership('test2', 'test')
|
mockNotePermissions('test2', 'test')
|
||||||
const testAlias: Alias = {
|
const testAlias: Alias = {
|
||||||
name: 'test-primary',
|
name: 'test-primary',
|
||||||
primaryAlias: true,
|
primaryAlias: true,
|
||||||
|
@ -70,7 +65,7 @@ describe('AliasesListEntry', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders an AliasesListEntry that is not primary', async () => {
|
it('renders an AliasesListEntry that is not primary', async () => {
|
||||||
mockNoteOwnership('test', 'test')
|
mockNotePermissions('test', 'test')
|
||||||
const testAlias: Alias = {
|
const testAlias: Alias = {
|
||||||
name: 'test-non-primary',
|
name: 'test-non-primary',
|
||||||
primaryAlias: false,
|
primaryAlias: false,
|
||||||
|
@ -95,7 +90,7 @@ describe('AliasesListEntry', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("disables button in AliasesListEntry if it's not primary", () => {
|
it("disables button in AliasesListEntry if it's not primary", () => {
|
||||||
mockNoteOwnership('test2', 'test')
|
mockNotePermissions('test2', 'test')
|
||||||
const testAlias: Alias = {
|
const testAlias: Alias = {
|
||||||
name: 'test-primary',
|
name: 'test-primary',
|
||||||
primaryAlias: false,
|
primaryAlias: false,
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import type { Alias } from '../../../../../../api/alias/types'
|
|
||||||
import * as useApplicationStateModule from '../../../../../../hooks/common/use-application-state'
|
|
||||||
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
||||||
import { AliasesList } from './aliases-list'
|
import { AliasesList } from './aliases-list'
|
||||||
import type { AliasesListEntryProps } from './aliases-list-entry'
|
import type { AliasesListEntryProps } from './aliases-list-entry'
|
||||||
import * as AliasesListEntryModule from './aliases-list-entry'
|
import * as AliasesListEntryModule from './aliases-list-entry'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { mockAppState } from '../../../../../../test-utils/mock-app-state'
|
||||||
|
|
||||||
jest.mock('../../../../../../hooks/common/use-application-state')
|
jest.mock('../../../../../../hooks/common/use-application-state')
|
||||||
jest.mock('./aliases-list-entry')
|
jest.mock('./aliases-list-entry')
|
||||||
|
@ -18,23 +17,27 @@ jest.mock('./aliases-list-entry')
|
||||||
describe('AliasesList', () => {
|
describe('AliasesList', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mockI18n()
|
await mockI18n()
|
||||||
jest.spyOn(useApplicationStateModule, 'useApplicationState').mockReturnValue([
|
mockAppState({
|
||||||
{
|
noteDetails: {
|
||||||
name: 'a-test',
|
aliases: [
|
||||||
noteId: 'note-id',
|
{
|
||||||
primaryAlias: false
|
name: 'a-test',
|
||||||
},
|
noteId: 'note-id',
|
||||||
{
|
primaryAlias: false
|
||||||
name: 'z-test',
|
},
|
||||||
noteId: 'note-id',
|
{
|
||||||
primaryAlias: false
|
name: 'z-test',
|
||||||
},
|
noteId: 'note-id',
|
||||||
{
|
primaryAlias: false
|
||||||
name: 'b-test',
|
},
|
||||||
noteId: 'note-id',
|
{
|
||||||
primaryAlias: true
|
name: 'b-test',
|
||||||
|
noteId: 'note-id',
|
||||||
|
primaryAlias: true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
] as Alias[])
|
})
|
||||||
jest.spyOn(AliasesListEntryModule, 'AliasesListEntry').mockImplementation((({ alias }) => {
|
jest.spyOn(AliasesListEntryModule, 'AliasesListEntry').mockImplementation((({ alias }) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../../../../test-utils/mock-i18n'
|
||||||
import type { CommonModalProps } from '../../../../../common/modals/common-modal'
|
import type { CommonModalProps } from '../../../../../common/modals/common-modal'
|
||||||
import * as CommonModalModule from '../../../../../common/modals/common-modal'
|
import * as CommonModalModule from '../../../../../common/modals/common-modal'
|
||||||
import * as useUiNotificationsModule from '../../../../../notifications/ui-notification-boundary'
|
|
||||||
import * as AliasesAddFormModule from './aliases-add-form'
|
import * as AliasesAddFormModule from './aliases-add-form'
|
||||||
import * as AliasesListModule from './aliases-list'
|
import * as AliasesListModule from './aliases-list'
|
||||||
import { AliasesModal } from './aliases-modal'
|
import { AliasesModal } from './aliases-modal'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import type { PropsWithChildren } from 'react'
|
import type { PropsWithChildren } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
|
||||||
|
|
||||||
jest.mock('./aliases-list')
|
jest.mock('./aliases-list')
|
||||||
jest.mock('./aliases-add-form')
|
jest.mock('./aliases-add-form')
|
||||||
|
@ -22,6 +22,7 @@ jest.mock('../../../../../notifications/ui-notification-boundary')
|
||||||
describe('AliasesModal', () => {
|
describe('AliasesModal', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mockI18n()
|
await mockI18n()
|
||||||
|
mockUiNotifications()
|
||||||
jest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children }) => {
|
jest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children }) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
@ -35,11 +36,6 @@ describe('AliasesModal', () => {
|
||||||
jest.spyOn(AliasesAddFormModule, 'AliasesAddForm').mockImplementation((() => {
|
jest.spyOn(AliasesAddFormModule, 'AliasesAddForm').mockImplementation((() => {
|
||||||
return <span>This is a mock for the AliasesAddForm that is tested separately.</span>
|
return <span>This is a mock for the AliasesAddForm that is tested separately.</span>
|
||||||
}) as React.FC)
|
}) as React.FC)
|
||||||
jest.spyOn(useUiNotificationsModule, 'useUiNotifications').mockReturnValue({
|
|
||||||
showErrorNotification: jest.fn(),
|
|
||||||
dismissNotification: jest.fn(),
|
|
||||||
dispatchUiNotification: jest.fn()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import type { DarkModeConfig, DarkModeConfigAction } from './types'
|
||||||
import { DarkModeConfigActionType, DarkModePreference } from './types'
|
import { DarkModeConfigActionType, DarkModePreference } from './types'
|
||||||
import type { Reducer } from 'redux'
|
import type { Reducer } from 'redux'
|
||||||
|
|
||||||
const initialState: DarkModeConfig = {
|
export const initialState: DarkModeConfig = {
|
||||||
darkModePreference: DarkModePreference.AUTO
|
darkModePreference: DarkModePreference.AUTO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
@ -10,7 +10,7 @@ import { Logger } from '../../utils/logger'
|
||||||
|
|
||||||
const logger = new Logger('EditorConfig Local Storage')
|
const logger = new Logger('EditorConfig Local Storage')
|
||||||
|
|
||||||
const initialState: EditorConfig = {
|
export const initialState: EditorConfig = {
|
||||||
ligatures: true,
|
ligatures: true,
|
||||||
syncScroll: true,
|
syncScroll: true,
|
||||||
smartPaste: true,
|
smartPaste: true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import type { RealtimeStatus, RealtimeStatusActions } from './types'
|
||||||
import { RealtimeStatusActionType } from './types'
|
import { RealtimeStatusActionType } from './types'
|
||||||
import type { Reducer } from 'redux'
|
import type { Reducer } from 'redux'
|
||||||
|
|
||||||
const initialState: RealtimeStatus = {
|
export const initialState: RealtimeStatus = {
|
||||||
isSynced: false,
|
isSynced: false,
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
onlineUsers: [],
|
onlineUsers: [],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import type { RendererStatus, RendererStatusActions } from './types'
|
||||||
import { RendererStatusActionType } from './types'
|
import { RendererStatusActionType } from './types'
|
||||||
import type { Reducer } from 'redux'
|
import type { Reducer } from 'redux'
|
||||||
|
|
||||||
const initialState: RendererStatus = {
|
export const initialState: RendererStatus = {
|
||||||
rendererReady: false
|
rendererReady: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
56
frontend/src/test-utils/mock-app-state.ts
Normal file
56
frontend/src/test-utils/mock-app-state.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import * as useApplicationStateModule from '../hooks/common/use-application-state'
|
||||||
|
import type { ApplicationState } from '../redux/application-state'
|
||||||
|
import type { DeepPartial } from 'redux'
|
||||||
|
import { initialState as initialStateDarkMode } from '../redux/dark-mode/reducers'
|
||||||
|
import { initialState as initialStateEditorConfig } from '../redux/editor/reducers'
|
||||||
|
import { initialState as initialStateNoteDetails } from '../redux/note-details/initial-state'
|
||||||
|
import { initialState as initialStateRealtimeStatus } from '../redux/realtime/reducers'
|
||||||
|
import { initialState as initialStateRendererStatus } from '../redux/renderer-status/reducers'
|
||||||
|
import type { NoteDetails } from '../redux/note-details/types/note-details'
|
||||||
|
import type { RealtimeStatus } from '../redux/realtime/types'
|
||||||
|
import type { HistoryEntryWithOrigin } from '../api/history/types'
|
||||||
|
|
||||||
|
jest.mock('../redux/editor/methods', () => ({
|
||||||
|
loadFromLocalStorage: jest.fn().mockReturnValue(undefined)
|
||||||
|
}))
|
||||||
|
jest.mock('../hooks/common/use-application-state')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks the {@link ApplicationState} for a test.
|
||||||
|
* When not overriden, it uses the initial state of the reducers.
|
||||||
|
*
|
||||||
|
* @param state Overrides for the mocked state
|
||||||
|
*/
|
||||||
|
export const mockAppState = (state?: DeepPartial<ApplicationState>) => {
|
||||||
|
jest.spyOn(useApplicationStateModule, 'useApplicationState').mockImplementation((fn) => {
|
||||||
|
return fn({
|
||||||
|
darkMode: {
|
||||||
|
...initialStateDarkMode,
|
||||||
|
...state?.darkMode
|
||||||
|
},
|
||||||
|
editorConfig: {
|
||||||
|
...initialStateEditorConfig,
|
||||||
|
...state?.editorConfig
|
||||||
|
},
|
||||||
|
history: (state?.history ?? []) as HistoryEntryWithOrigin[],
|
||||||
|
noteDetails: {
|
||||||
|
...initialStateNoteDetails,
|
||||||
|
...state?.noteDetails
|
||||||
|
} as NoteDetails,
|
||||||
|
realtimeStatus: {
|
||||||
|
...initialStateRealtimeStatus,
|
||||||
|
...state?.realtimeStatus
|
||||||
|
} as RealtimeStatus,
|
||||||
|
rendererStatus: {
|
||||||
|
...initialStateRendererStatus,
|
||||||
|
...state?.rendererStatus
|
||||||
|
},
|
||||||
|
user: state?.user ?? null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
43
frontend/src/test-utils/mock-note-permissions.ts
Normal file
43
frontend/src/test-utils/mock-note-permissions.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import type { ApplicationState } from '../redux/application-state'
|
||||||
|
import type { DeepPartial } from 'redux'
|
||||||
|
import { mockAppState } from './mock-app-state'
|
||||||
|
import type { LoginUserInfo } from '../api/me/types'
|
||||||
|
import type { NotePermissions } from '@hedgedoc/commons'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks the {@link NotePermissions} field of a note in the {@link ApplicationState }for a test.
|
||||||
|
* This test-util should not be used alongside {@link mockAppState} to avoid overwriting the mocked state.
|
||||||
|
*
|
||||||
|
* @param ownUsername The name of the own user to set in the state (for comparing note ownership)
|
||||||
|
* @param noteOwner The owner's username of the mocked note
|
||||||
|
* @param permissions Overrides for the mocked permissions
|
||||||
|
* @param additionalState Overrides for the overall mocked application state
|
||||||
|
*/
|
||||||
|
export const mockNotePermissions = (
|
||||||
|
ownUsername: string,
|
||||||
|
noteOwner: string,
|
||||||
|
permissions?: DeepPartial<NotePermissions>,
|
||||||
|
additionalState?: DeepPartial<ApplicationState>
|
||||||
|
) => {
|
||||||
|
mockAppState({
|
||||||
|
...additionalState,
|
||||||
|
noteDetails: {
|
||||||
|
...additionalState?.noteDetails,
|
||||||
|
permissions: {
|
||||||
|
sharedToGroups: [],
|
||||||
|
sharedToUsers: [],
|
||||||
|
...permissions,
|
||||||
|
owner: noteOwner
|
||||||
|
}
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
...additionalState?.user,
|
||||||
|
username: ownUsername
|
||||||
|
} as LoginUserInfo
|
||||||
|
})
|
||||||
|
}
|
19
frontend/src/test-utils/mock-ui-notifications.ts
Normal file
19
frontend/src/test-utils/mock-ui-notifications.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import * as useUiNotificationsModule from '../components/notifications/ui-notification-boundary'
|
||||||
|
|
||||||
|
jest.mock('../components/notifications/ui-notification-boundary')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks the {@link useUiNotifications} hook with stub functions for tests.
|
||||||
|
*/
|
||||||
|
export const mockUiNotifications = () => {
|
||||||
|
jest.spyOn(useUiNotificationsModule, 'useUiNotifications').mockReturnValue({
|
||||||
|
showErrorNotification: jest.fn(),
|
||||||
|
dismissNotification: jest.fn(),
|
||||||
|
dispatchUiNotification: jest.fn()
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
import * as useApplicationStateModule from '../hooks/common/use-application-state'
|
|
||||||
import type { ApplicationState } from '../redux/application-state'
|
|
||||||
|
|
||||||
jest.mock('../hooks/common/use-application-state')
|
|
||||||
export const mockNoteOwnership = (
|
|
||||||
ownUsername: string,
|
|
||||||
noteOwner: string,
|
|
||||||
additionalState?: Partial<ApplicationState>
|
|
||||||
) => {
|
|
||||||
jest.spyOn(useApplicationStateModule, 'useApplicationState').mockImplementation((fn) => {
|
|
||||||
return fn({
|
|
||||||
...additionalState,
|
|
||||||
noteDetails: {
|
|
||||||
...additionalState?.noteDetails,
|
|
||||||
permissions: {
|
|
||||||
owner: noteOwner
|
|
||||||
}
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
...additionalState?.user,
|
|
||||||
username: ownUsername
|
|
||||||
}
|
|
||||||
} as ApplicationState)
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in a new issue