test(frontend): replace jest with vitest

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2025-04-26 14:27:29 +02:00
parent 5241a6e988
commit 49bbd32635
No known key found for this signature in database
GPG key ID: FE1CD209E3EA5E85
188 changed files with 1364 additions and 1212 deletions

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { extractFrontmatter } from './extractor.js' import { extractFrontmatter } from './extractor.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('frontmatter extraction', () => { describe('frontmatter extraction', () => {
describe('isPresent property', () => { describe('isPresent property', () => {

View file

@ -11,7 +11,7 @@ import {
} from '../note-frontmatter/frontmatter.js' } from '../note-frontmatter/frontmatter.js'
import { SlideOptions } from '../note-frontmatter/slide-show-options.js' import { SlideOptions } from '../note-frontmatter/slide-show-options.js'
import { convertRawFrontmatterToNoteFrontmatter } from './convert-raw-frontmatter-to-note-frontmatter.js' import { convertRawFrontmatterToNoteFrontmatter } from './convert-raw-frontmatter-to-note-frontmatter.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('convertRawFrontmatterToNoteFrontmatter', () => { describe('convertRawFrontmatterToNoteFrontmatter', () => {
it.each([false, true])( it.each([false, true])(

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { parseRawFrontmatterFromYaml } from './parse-raw-frontmatter-from-yaml.js' import { parseRawFrontmatterFromYaml } from './parse-raw-frontmatter-from-yaml.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('yaml frontmatter', () => { describe('yaml frontmatter', () => {
it('should parse "title"', () => { it('should parse "title"', () => {

View file

@ -5,7 +5,7 @@
*/ */
import { NoSubdirectoryAllowedError, WrongProtocolError } from './errors.js' import { NoSubdirectoryAllowedError, WrongProtocolError } from './errors.js'
import { parseUrl } from './parse-url.js' import { parseUrl } from './parse-url.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('validate url', () => { describe('validate url', () => {
it("doesn't accept non-urls", () => { it("doesn't accept non-urls", () => {

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { userCanEdit, userIsOwner } from './permissions.js' import { userCanEdit, userIsOwner } from './permissions.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { NotePermissionsDto, SpecialGroup } from '../dtos/index.js' import { NotePermissionsDto, SpecialGroup } from '../dtos/index.js'
describe('Permissions', () => { describe('Permissions', () => {

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { extractFirstHeading } from './extract-first-heading.js' import { extractFirstHeading } from './extract-first-heading.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { Document, Element, Text } from 'domhandler' import { Document, Element, Text } from 'domhandler'
describe('extract first heading', () => { describe('extract first heading', () => {

View file

@ -9,7 +9,7 @@ import {
NoteType, NoteType,
} from '../note-frontmatter/frontmatter.js' } from '../note-frontmatter/frontmatter.js'
import { generateNoteTitle } from './generate-note-title.js' import { generateNoteTitle } from './generate-note-title.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
const testFrontmatter: NoteFrontmatter = { const testFrontmatter: NoteFrontmatter = {
title: '', title: '',

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { RealtimeDoc } from './realtime-doc.js' import { RealtimeDoc } from './realtime-doc.js'
import { describe, expect, it } from 'vitest' import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('realtime doc', () => { describe('realtime doc', () => {
it('saves an initial text content correctly', () => { it('saves an initial text content correctly', () => {

View file

@ -19,9 +19,9 @@
"test:e2e:open": "cypress open", "test:e2e:open": "cypress open",
"test:e2e": "cypress run --browser chrome", "test:e2e": "cypress run --browser chrome",
"test:e2e:ci": "cypress run --browser chrome --record true --parallel --group \"chrome\"", "test:e2e:ci": "cypress run --browser chrome --record true --parallel --group \"chrome\"",
"test:watch": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test jest --watch", "test:watch": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test vitest --watch",
"test:ci": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test jest --coverage", "test:ci": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test vitest --coverage",
"test": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test jest" "test": "cross-env NODE_OPTIONS=\"${NODE_OPTIONS:-} --experimental-vm-modules\" NODE_ENV=test vitest"
}, },
"browserslist": [ "browserslist": [
"Chrome 118", "Chrome 118",
@ -131,7 +131,6 @@
"@types/d3-graphviz": "2.6.10", "@types/d3-graphviz": "2.6.10",
"@types/diff": "6.0.0", "@types/diff": "6.0.0",
"@types/dompurify": "3.0.5", "@types/dompurify": "3.0.5",
"@types/jest": "29.5.14",
"@types/katex": "0.16.7", "@types/katex": "0.16.7",
"@types/luxon": "3.4.2", "@types/luxon": "3.4.2",
"@types/markdown-it": "13.0.8", "@types/markdown-it": "13.0.8",
@ -141,6 +140,7 @@
"@types/react": "19.1.2", "@types/react": "19.1.2",
"@types/react-dom": "19.1.2", "@types/react-dom": "19.1.2",
"@types/ws": "8.5.12", "@types/ws": "8.5.12",
"@vitejs/plugin-react": "4.4.1",
"csstype": "3.1.3", "csstype": "3.1.3",
"cypress": "13.17.0", "cypress": "13.17.0",
"cypress-commands": "3.0.0", "cypress-commands": "3.0.0",
@ -156,8 +156,7 @@
"eslint-plugin-prettier": "5.2.6", "eslint-plugin-prettier": "5.2.6",
"eslint-plugin-promise": "7.2.1", "eslint-plugin-promise": "7.2.1",
"eslint-plugin-testing-library": "7.1.1", "eslint-plugin-testing-library": "7.1.1",
"jest": "29.7.0", "jsdom": "26.1.0",
"jest-environment-jsdom": "29.7.0",
"prettier": "3.3.3", "prettier": "3.3.3",
"react-test-renderer": "18.3.1", "react-test-renderer": "18.3.1",
"ts-loader": "9.5.2", "ts-loader": "9.5.2",
@ -165,7 +164,8 @@
"ts-node": "11.0.0-beta.1", "ts-node": "11.0.0-beta.1",
"typescript": "5.6.3", "typescript": "5.6.3",
"typescript-eslint": "8.31.0", "typescript-eslint": "8.31.0",
"user-agent-data-types": "0.4.2" "user-agent-data-types": "0.4.2",
"vitest": "3.1.2"
}, },
"packageManager": "yarn@4.5.3", "packageManager": "yarn@4.5.3",
"resolutions": { "resolutions": {

View file

@ -7,6 +7,7 @@ import { ApiError } from '../api-error'
import type { ApiErrorResponse } from '../api-error-response' import type { ApiErrorResponse } from '../api-error-response'
import { DeleteApiRequestBuilder } from './delete-api-request-builder' import { DeleteApiRequestBuilder } from './delete-api-request-builder'
import { expectFetch } from './test-utils/expect-fetch' import { expectFetch } from './test-utils/expect-fetch'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('DeleteApiRequestBuilder', () => { describe('DeleteApiRequestBuilder', () => {
let originalFetch: (typeof global)['fetch'] let originalFetch: (typeof global)['fetch']

View file

@ -7,6 +7,7 @@ import { ApiError } from '../api-error'
import type { ApiErrorResponse } from '../api-error-response' import type { ApiErrorResponse } from '../api-error-response'
import { GetApiRequestBuilder } from './get-api-request-builder' import { GetApiRequestBuilder } from './get-api-request-builder'
import { expectFetch } from './test-utils/expect-fetch' import { expectFetch } from './test-utils/expect-fetch'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('GetApiRequestBuilder', () => { describe('GetApiRequestBuilder', () => {
let originalFetch: (typeof global)['fetch'] let originalFetch: (typeof global)['fetch']

View file

@ -7,6 +7,7 @@ import { ApiError } from '../api-error'
import type { ApiErrorResponse } from '../api-error-response' import type { ApiErrorResponse } from '../api-error-response'
import { PostApiRequestBuilder } from './post-api-request-builder' import { PostApiRequestBuilder } from './post-api-request-builder'
import { expectFetch } from './test-utils/expect-fetch' import { expectFetch } from './test-utils/expect-fetch'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('PostApiRequestBuilder', () => { describe('PostApiRequestBuilder', () => {
let originalFetch: (typeof global)['fetch'] let originalFetch: (typeof global)['fetch']

View file

@ -7,6 +7,7 @@ import { ApiError } from '../api-error'
import type { ApiErrorResponse } from '../api-error-response' import type { ApiErrorResponse } from '../api-error-response'
import { PutApiRequestBuilder } from './put-api-request-builder' import { PutApiRequestBuilder } from './put-api-request-builder'
import { expectFetch } from './test-utils/expect-fetch' import { expectFetch } from './test-utils/expect-fetch'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('PutApiRequestBuilder', () => { describe('PutApiRequestBuilder', () => {
let originalFetch: (typeof global)['fetch'] let originalFetch: (typeof global)['fetch']

View file

@ -5,6 +5,7 @@
*/ */
import { defaultConfig } from '../../default-config' import { defaultConfig } from '../../default-config'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { vi, expect } from 'vitest'
/** /**
* Mock fetch api for tests. * Mock fetch api for tests.
@ -20,7 +21,7 @@ export const expectFetch = (
expectedOptions: RequestInit, expectedOptions: RequestInit,
responseBody?: unknown responseBody?: unknown
): void => { ): void => {
global.fetch = jest.fn((fetchUrl: RequestInfo | URL, fetchOptions?: RequestInit): Promise<Response> => { global.fetch = vi.fn((fetchUrl: RequestInfo | URL, fetchOptions?: RequestInit): Promise<Response> => {
expect(fetchUrl).toEqual(expectedUrl) expect(fetchUrl).toEqual(expectedUrl)
expect(fetchOptions).toStrictEqual({ expect(fetchOptions).toStrictEqual({
...defaultConfig, ...defaultConfig,
@ -32,7 +33,7 @@ export const expectFetch = (
Mock.of<Response>({ Mock.of<Response>({
status: requestStatusCode, status: requestStatusCode,
statusText: mapCodeToText(requestStatusCode), statusText: mapCodeToText(requestStatusCode),
json: jest.fn(() => (responseBody ? Promise.resolve(responseBody) : Promise.reject(new Error()))) json: vi.fn(() => (responseBody ? Promise.resolve(responseBody) : Promise.reject(new Error())))
}) })
) )
}) as typeof global.fetch }) as typeof global.fetch

View file

@ -5,6 +5,7 @@
*/ */
import { ApiResponse } from './api-response' import { ApiResponse } from './api-response'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('ApiResponse', () => { describe('ApiResponse', () => {
it('getResponse returns input response', () => { it('getResponse returns input response', () => {

View file

@ -5,6 +5,7 @@
*/ */
import { ApiError } from './api-error' import { ApiError } from './api-error'
import { ErrorToI18nKeyMapper } from './error-to-i18n-key-mapper' import { ErrorToI18nKeyMapper } from './error-to-i18n-key-mapper'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('ErrorToI18nKeyMapper', () => { describe('ErrorToI18nKeyMapper', () => {
it('returns fallback with namespace when no mapper is defined', () => { it('returns fallback with namespace when no mapper is defined', () => {

View file

@ -1,20 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`app bar contains alert when editor is not synced 1`] = ` exports[`app bar > contains alert when editor is not synced 1`] = `
<div> <div>
<div> <div>
<span> <span>
first part first part
</span> </span>
<div> <div />
<div
class="fade w-100 m-0 px-2 py-1 border-top-0 border-bottom-0 d-flex align-items-center alert alert-warning show"
role="alert"
>
realtime.connecting
BootstrapIconMock_ArrowRepeat
</div>
</div>
<span> <span>
last part last part
</span> </span>
@ -22,24 +14,13 @@ exports[`app bar contains alert when editor is not synced 1`] = `
</div> </div>
`; `;
exports[`app bar contains note title and read-only marker when having only read permissions 1`] = ` exports[`app bar > contains note title and read-only marker when having only read permissions 1`] = `
<div> <div>
<div> <div>
<span> <span>
first part first part
</span> </span>
<div> <div />
<span
class="m-0 text-truncate"
>
<span
class="text-secondary me-2"
>
BootstrapIconMock_Lock
</span>
Note Title Test
</span>
</div>
<span> <span>
last part last part
</span> </span>
@ -47,19 +28,13 @@ exports[`app bar contains note title and read-only marker when having only read
</div> </div>
`; `;
exports[`app bar contains note title when editor is synced 1`] = ` exports[`app bar > contains note title when editor is synced 1`] = `
<div> <div>
<div> <div>
<span> <span>
first part first part
</span> </span>
<div> <div />
<span
class="m-0 text-truncate"
>
Note Title Test
</span>
</div>
<span> <span>
last part last part
</span> </span>

View file

@ -10,8 +10,9 @@ 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 { mockAppState } from '../../../../../test-utils/mock-app-state'
import { vi, describe, it, beforeAll, afterAll, expect } from 'vitest'
jest.mock('../../../../../components/layout/app-bar/base-app-bar', () => ({ vi.mock('../../../../../components/layout/app-bar/base-app-bar', () => ({
__esModule: true, __esModule: true,
BaseAppBar: ({ children }: PropsWithChildren) => ( BaseAppBar: ({ children }: PropsWithChildren) => (
<div> <div>
@ -21,7 +22,7 @@ jest.mock('../../../../../components/layout/app-bar/base-app-bar', () => ({
</div> </div>
) )
})) }))
jest.mock('../../../../../hooks/common/use-application-state') vi.mock('../../../../../hooks/common/use-application-state')
const mockedCommonAppState = { const mockedCommonAppState = {
noteDetails: { noteDetails: {
@ -44,7 +45,7 @@ const mockedCommonAppState = {
describe('app bar', () => { describe('app bar', () => {
beforeAll(mockI18n) beforeAll(mockI18n)
afterAll(() => jest.restoreAllMocks()) afterAll(() => vi.restoreAllMocks())
it('contains note title when editor is synced', () => { it('contains note title when editor is synced', () => {
mockAppState({ mockAppState({

View file

@ -1,15 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ApplicationErrorAlert renders correctly 1`] = ` exports[`ApplicationErrorAlert > renders correctly 1`] = `
<div> <div>
<div <div
class="fade alert test-class alert alert-primary show" class="fade _alert_663ce3 test-class alert alert-primary show"
role="alert" role="alert"
> >
<p <p
class="d-flex align-items-center" class="d-flex align-items-center"
> >
This is a mock for "AlertIcon". Props: {"className":"logo"} This is a mock for "AlertIcon". Props: {"className":"_logo_663ce3"}
<span> <span>
<span> <span>
Test Child Test Child

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`TranslatedApplicationErrorAlert renders correctly 1`] = ` exports[`TranslatedApplicationErrorAlert > renders correctly 1`] = `
<div> <div>
<div> <div>
<h3> <h3>

View file

@ -7,8 +7,10 @@
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { ApplicationErrorAlert } from './application-error-alert' import { ApplicationErrorAlert } from './application-error-alert'
import type { AlertIconProps } from './alert-icon' import type { AlertIconProps } from './alert-icon'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('./alert-icon', () => ({ vi.mock('./alert-icon', () => ({
AlertIcon: (props: AlertIconProps) => `This is a mock for "AlertIcon". Props: ${JSON.stringify(props)}` AlertIcon: (props: AlertIconProps) => `This is a mock for "AlertIcon". Props: ${JSON.stringify(props)}`
})) }))

View file

@ -9,8 +9,10 @@ import { mockI18n } from '../../../test-utils/mock-i18n'
import { TranslatedApplicationErrorAlert } from './translated-application-error-alert' import { TranslatedApplicationErrorAlert } from './translated-application-error-alert'
import type { PropsWithChildren } from 'react' import type { PropsWithChildren } from 'react'
import React from 'react' import React from 'react'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('./application-error-alert', () => ({ vi.mock('./application-error-alert', () => ({
ApplicationErrorAlert: ({ children, ...props }: PropsWithChildren) => ( ApplicationErrorAlert: ({ children, ...props }: PropsWithChildren) => (
<div> <div>
<h3>This is a mock for ApplicationErrorAlert.</h3> <h3>This is a mock for ApplicationErrorAlert.</h3>

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Async loading boundary shows a waiting spinner if loading 1`] = ` exports[`Async loading boundary > shows a waiting spinner if loading 1`] = `
<div> <div>
<div <div
class="m-3 d-flex align-items-center justify-content-center" class="m-3 d-flex align-items-center justify-content-center"
@ -10,7 +10,7 @@ exports[`Async loading boundary shows a waiting spinner if loading 1`] = `
</div> </div>
`; `;
exports[`Async loading boundary shows an error if error is given with loading 1`] = ` exports[`Async loading boundary > shows an error if error is given with loading 1`] = `
<div> <div>
<div <div
class="fade alert alert-danger show" class="fade alert alert-danger show"
@ -21,7 +21,7 @@ exports[`Async loading boundary shows an error if error is given with loading 1`
</div> </div>
`; `;
exports[`Async loading boundary shows an error if error is given without loading 1`] = ` exports[`Async loading boundary > shows an error if error is given without loading 1`] = `
<div> <div>
<div <div
class="fade alert alert-danger show" class="fade alert alert-danger show"
@ -32,7 +32,7 @@ exports[`Async loading boundary shows an error if error is given without loading
</div> </div>
`; `;
exports[`Async loading boundary shows the children if not loading and no error 1`] = ` exports[`Async loading boundary > shows the children if not loading and no error 1`] = `
<div> <div>
children children
</div> </div>

View file

@ -1,24 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Custom error async loading boundary shows a waiting spinner if loading 1`] = ` exports[`Custom error async loading boundary > shows a waiting spinner if loading 1`] = `
<div> <div>
wait wait
</div> </div>
`; `;
exports[`Custom error async loading boundary shows an error if error is given with loading 1`] = ` exports[`Custom error async loading boundary > shows an error if error is given with loading 1`] = `
<div> <div>
error error
</div> </div>
`; `;
exports[`Custom error async loading boundary shows an error if error is given without loading 1`] = ` exports[`Custom error async loading boundary > shows an error if error is given without loading 1`] = `
<div> <div>
error error
</div> </div>
`; `;
exports[`Custom error async loading boundary shows the children if not loading and no error 1`] = ` exports[`Custom error async loading boundary > shows the children if not loading and no error 1`] = `
<div> <div>
children children
</div> </div>

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { AsyncLoadingBoundary } from './async-loading-boundary' import { AsyncLoadingBoundary } from './async-loading-boundary'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Async loading boundary', () => { describe('Async loading boundary', () => {
beforeAll(() => mockI18n()) beforeAll(() => mockI18n())

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { CustomAsyncLoadingBoundary } from './custom-async-loading-boundary' import { CustomAsyncLoadingBoundary } from './custom-async-loading-boundary'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Custom error async loading boundary', () => { describe('Custom error async loading boundary', () => {
beforeAll(() => mockI18n()) beforeAll(() => mockI18n())

View file

@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Copy to clipboard button show an error text if clipboard api isn't available 1`] = ` exports[`Copy to clipboard button > show an error text if clipboard api isn't available 1`] = `
<div> <div>
<button <button
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >
@ -12,11 +12,11 @@ exports[`Copy to clipboard button show an error text if clipboard api isn't avai
</div> </div>
`; `;
exports[`Copy to clipboard button show an error text if clipboard api isn't available 2`] = ` exports[`Copy to clipboard button > show an error text if clipboard api isn't available 2`] = `
<div> <div>
<button <button
aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb" aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb"
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >
@ -25,10 +25,10 @@ exports[`Copy to clipboard button show an error text if clipboard api isn't avai
</div> </div>
`; `;
exports[`Copy to clipboard button shows an error text if writing failed 1`] = ` exports[`Copy to clipboard button > shows an error text if writing failed 1`] = `
<div> <div>
<button <button
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >
@ -37,11 +37,11 @@ exports[`Copy to clipboard button shows an error text if writing failed 1`] = `
</div> </div>
`; `;
exports[`Copy to clipboard button shows an error text if writing failed 2`] = ` exports[`Copy to clipboard button > shows an error text if writing failed 2`] = `
<div> <div>
<button <button
aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb" aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb"
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >
@ -50,10 +50,10 @@ exports[`Copy to clipboard button shows an error text if writing failed 2`] = `
</div> </div>
`; `;
exports[`Copy to clipboard button shows an success text if writing succeeded 1`] = ` exports[`Copy to clipboard button > shows an success text if writing succeeded 1`] = `
<div> <div>
<button <button
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >
@ -62,11 +62,11 @@ exports[`Copy to clipboard button shows an success text if writing succeeded 1`]
</div> </div>
`; `;
exports[`Copy to clipboard button shows an success text if writing succeeded 2`] = ` exports[`Copy to clipboard button > shows an success text if writing succeeded 2`] = `
<div> <div>
<button <button
aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb" aria-describedby="copied_35a35a31-c259-48c4-b75a-8da99859dcdb"
class="copy-button btn btn-dark btn-sm" class="_copy-button_45cbcd btn btn-dark btn-sm"
title="renderer.highlightCode.copyCode" title="renderer.highlightCode.copyCode"
type="button" type="button"
> >

View file

@ -8,8 +8,10 @@ import { CopyToClipboardButton } from './copy-to-clipboard-button'
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 * as uuidModule from 'uuid' import * as uuidModule from 'uuid'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('uuid') vi.mock('uuid')
describe('Copy to clipboard button', () => { describe('Copy to clipboard button', () => {
const copyContent = 'Copy McCopy Content. Electric Copyloo' const copyContent = 'Copy McCopy Content. Electric Copyloo'
@ -20,15 +22,15 @@ describe('Copy to clipboard button', () => {
beforeAll(async () => { beforeAll(async () => {
await mockI18n() await mockI18n()
originalClipboard = window.navigator.clipboard originalClipboard = window.navigator.clipboard
jest.spyOn(uuidModule, 'v4').mockReturnValue(Buffer.from(uuidMock)) vitest.spyOn(uuidModule, 'v4').mockReturnValue(Buffer.from(uuidMock))
}) })
afterAll(() => { afterAll(() => {
Object.assign(global.navigator, { Object.assign(global.navigator, {
clipboard: originalClipboard clipboard: originalClipboard
}) })
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
const testButton = async (expectSuccess: boolean) => { const testButton = async (expectSuccess: boolean) => {
@ -44,8 +46,8 @@ describe('Copy to clipboard button', () => {
expect(view.container).toMatchSnapshot() expect(view.container).toMatchSnapshot()
} }
const mockClipboard = (copyIsSuccessful: boolean): jest.Mock => { const mockClipboard = (copyIsSuccessful: boolean): vi.mock => {
const writeTextToClipboardSpy = jest.fn(() => const writeTextToClipboardSpy = vitest.fn(() =>
copyIsSuccessful ? Promise.resolve() : Promise.reject(new Error('mocked clipboard failed')) copyIsSuccessful ? Promise.resolve() : Promise.reject(new Error('mocked clipboard failed'))
) )
Object.assign(global.navigator, { Object.assign(global.navigator, {

View file

@ -1,91 +1,91 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`custom branding doesn't show anything if no branding is defined 1`] = `<div />`; exports[`custom branding > doesn't show anything if no branding is defined 1`] = `<div />`;
exports[`custom branding with inline=false shows an image if branding logo is defined 1`] = ` exports[`custom branding > with inline=false > shows an image if branding logo is defined 1`] = `
<div> <div>
<img <img
class="regular-size" class="_regular-size_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
/> />
</div> </div>
`; `;
exports[`custom branding with inline=false shows an text if branding text is defined 1`] = ` exports[`custom branding > with inline=false > shows an text if branding text is defined 1`] = `
<div> <div>
<span <span
class="regular-size" class="_regular-size_4a21ce"
> >
mockedBranding mockedBranding
</span> </span>
</div> </div>
`; `;
exports[`custom branding with inline=false will prefer the logo over the text 1`] = ` exports[`custom branding > with inline=false > will prefer the logo over the text 1`] = `
<div> <div>
<img <img
alt="mockedBranding" alt="mockedBranding"
class="regular-size" class="_regular-size_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
title="mockedBranding" title="mockedBranding"
/> />
</div> </div>
`; `;
exports[`custom branding with inline=true shows an image if branding logo is defined 1`] = ` exports[`custom branding > with inline=true > shows an image if branding logo is defined 1`] = `
<div> <div>
<img <img
class="inline-logo" class="_inline-logo_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
/> />
</div> </div>
`; `;
exports[`custom branding with inline=true shows an text if branding text is defined 1`] = ` exports[`custom branding > with inline=true > shows an text if branding text is defined 1`] = `
<div> <div>
<span <span
class="inline-text" class="_inline-text_4a21ce"
> >
mockedBranding mockedBranding
</span> </span>
</div> </div>
`; `;
exports[`custom branding with inline=true will prefer the logo over the text 1`] = ` exports[`custom branding > with inline=true > will prefer the logo over the text 1`] = `
<div> <div>
<img <img
alt="mockedBranding" alt="mockedBranding"
class="inline-logo" class="_inline-logo_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
title="mockedBranding" title="mockedBranding"
/> />
</div> </div>
`; `;
exports[`custom branding with inline=undefined shows an image if branding logo is defined 1`] = ` exports[`custom branding > with inline=undefined > shows an image if branding logo is defined 1`] = `
<div> <div>
<img <img
class="regular-size" class="_regular-size_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
/> />
</div> </div>
`; `;
exports[`custom branding with inline=undefined shows an text if branding text is defined 1`] = ` exports[`custom branding > with inline=undefined > shows an text if branding text is defined 1`] = `
<div> <div>
<span <span
class="regular-size" class="_regular-size_4a21ce"
> >
mockedBranding mockedBranding
</span> </span>
</div> </div>
`; `;
exports[`custom branding with inline=undefined will prefer the logo over the text 1`] = ` exports[`custom branding > with inline=undefined > will prefer the logo over the text 1`] = `
<div> <div>
<img <img
alt="mockedBranding" alt="mockedBranding"
class="regular-size" class="_regular-size_4a21ce"
src="mockBrandingUrl" src="mockBrandingUrl"
title="mockedBranding" title="mockedBranding"
/> />

View file

@ -8,12 +8,14 @@ import * as UseFrontendConfigMock from '../frontend-config-context/use-frontend-
import { CustomBranding } from './custom-branding' import { CustomBranding } from './custom-branding'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../frontend-config-context/use-frontend-config') vi.mock('../frontend-config-context/use-frontend-config')
describe('custom branding', () => { describe('custom branding', () => {
const mockFrontendConfigHook = (logo: string | null = null, name: string | null = null) => { const mockFrontendConfigHook = (logo: string | null = null, name: string | null = null) => {
jest vi
.spyOn(UseFrontendConfigMock, 'useFrontendConfig') .spyOn(UseFrontendConfigMock, 'useFrontendConfig')
.mockReturnValue(Mock.of<FrontendConfigDto>({ branding: { logo, name } })) .mockReturnValue(Mock.of<FrontendConfigDto>({ branding: { logo, name } }))
} }

View file

@ -1,17 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Highlighted Code can hide the line numbers 1`] = ` exports[`Highlighted Code > can hide the line numbers 1`] = `
<code <code
class="hljs wrapLines" class="hljs _wrapLines_15d654"
data-testid="code-highlighter" data-testid="code-highlighter"
> >
<span <span
class="linenumber" class="_linenumber_15d654"
> >
1 1
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
const a = 1 const a = 1
@ -20,18 +20,18 @@ exports[`Highlighted Code can hide the line numbers 1`] = `
</code> </code>
`; `;
exports[`Highlighted Code highlights code 1`] = ` exports[`Highlighted Code > highlights code 1`] = `
<code <code
class="hljs showGutter" class="hljs _showGutter_15d654"
data-testid="code-highlighter" data-testid="code-highlighter"
> >
<span <span
class="linenumber" class="_linenumber_15d654"
> >
1 1
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span <span
class="hljs-keyword" class="hljs-keyword"
@ -48,42 +48,42 @@ exports[`Highlighted Code highlights code 1`] = `
</code> </code>
`; `;
exports[`Highlighted Code renders plain text 1`] = ` exports[`Highlighted Code > renders plain text 1`] = `
<code <code
class="hljs showGutter" class="hljs _showGutter_15d654"
data-testid="code-highlighter" data-testid="code-highlighter"
> >
<span <span
class="linenumber" class="_linenumber_15d654"
> >
1 1
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
a a
</span> </span>
</div> </div>
<span <span
class="linenumber" class="_linenumber_15d654"
> >
2 2
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
b b
</span> </span>
</div> </div>
<span <span
class="linenumber" class="_linenumber_15d654"
> >
3 3
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
c c
@ -92,18 +92,18 @@ exports[`Highlighted Code renders plain text 1`] = `
</code> </code>
`; `;
exports[`Highlighted Code starts with a specific line 1`] = ` exports[`Highlighted Code > starts with a specific line 1`] = `
<code <code
class="hljs showGutter wrapLines" class="hljs _showGutter_15d654 _wrapLines_15d654"
data-testid="code-highlighter" data-testid="code-highlighter"
> >
<span <span
class="linenumber" class="_linenumber_15d654"
> >
100 100
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
const a = 1 const a = 1
@ -112,18 +112,18 @@ exports[`Highlighted Code starts with a specific line 1`] = `
</code> </code>
`; `;
exports[`Highlighted Code wraps code 1`] = ` exports[`Highlighted Code > wraps code 1`] = `
<code <code
class="hljs showGutter wrapLines" class="hljs _showGutter_15d654 _wrapLines_15d654"
data-testid="code-highlighter" data-testid="code-highlighter"
> >
<span <span
class="linenumber" class="_linenumber_15d654"
> >
1 1
</span> </span>
<div <div
class="codeline" class="_codeline_15d654"
> >
<span> <span>
const a = 1 const a = 1

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import HighlightedCode from './highlighted-code' import HighlightedCode from './highlighted-code'
import { render, screen } from '@testing-library/react' import { render, screen } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Highlighted Code', () => { describe('Highlighted Code', () => {
beforeAll(() => mockI18n()) beforeAll(() => mockI18n())

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`HTML to React renders basic html correctly 1`] = ` exports[`HTML to React > renders basic html correctly 1`] = `
<div> <div>
<p> <p>
This is a test This is a test
@ -11,7 +11,7 @@ exports[`HTML to React renders basic html correctly 1`] = `
</div> </div>
`; `;
exports[`HTML to React will forward the DomPurify settings 1`] = ` exports[`HTML to React > will forward the DomPurify settings 1`] = `
<div> <div>
<test-tag> <test-tag>
Test! Test!
@ -19,7 +19,7 @@ exports[`HTML to React will forward the DomPurify settings 1`] = `
</div> </div>
`; `;
exports[`HTML to React will forward the parser options 1`] = ` exports[`HTML to React > will forward the parser options 1`] = `
<div> <div>
<p> <p>
Hijacked! Hijacked!
@ -27,7 +27,7 @@ exports[`HTML to React will forward the parser options 1`] = `
</div> </div>
`; `;
exports[`HTML to React will render links with non-http protocols 1`] = ` exports[`HTML to React > will render links with non-http protocols 1`] = `
<div> <div>
<a <a
href="tel:+1234567890" href="tel:+1234567890"
@ -52,7 +52,7 @@ exports[`HTML to React will render links with non-http protocols 1`] = `
</div> </div>
`; `;
exports[`HTML to React won't render script links 1`] = ` exports[`HTML to React > won't render script links 1`] = `
<div> <div>
<a> <a>
js js
@ -63,4 +63,4 @@ exports[`HTML to React won't render script links 1`] = `
</div> </div>
`; `;
exports[`HTML to React won't render script tags 1`] = `<div />`; exports[`HTML to React > won't render script tags 1`] = `<div />`;

View file

@ -5,6 +5,7 @@
*/ */
import { HtmlToReact } from './html-to-react' import { HtmlToReact } from './html-to-react'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('HTML to React', () => { describe('HTML to React', () => {
it('renders basic html correctly', () => { it('renders basic html correctly', () => {

View file

@ -6,13 +6,13 @@
import { measurePerformance } from '../../../utils/measure-performance' import { measurePerformance } from '../../../utils/measure-performance'
import type { ParserOptions } from '@hedgedoc/html-to-react' import type { ParserOptions } from '@hedgedoc/html-to-react'
import { convertHtmlToReact } from '@hedgedoc/html-to-react' import { convertHtmlToReact } from '@hedgedoc/html-to-react'
import type DOMPurify from 'dompurify' import type { Config } from 'dompurify'
import { sanitize } from 'dompurify' import DOMPurify from 'dompurify'
import React, { Fragment, useMemo } from 'react' import React, { Fragment, useMemo } from 'react'
export interface HtmlToReactProps { export interface HtmlToReactProps {
htmlCode: string htmlCode: string
domPurifyConfig?: DOMPurify.Config domPurifyConfig?: Config
parserOptions?: ParserOptions parserOptions?: ParserOptions
} }
@ -28,7 +28,7 @@ const REGEX_URI_SCHEME_NO_SCRIPTS = /^(?!.*script:).+:?/i
export const HtmlToReact: React.FC<HtmlToReactProps> = ({ htmlCode, domPurifyConfig, parserOptions }) => { export const HtmlToReact: React.FC<HtmlToReactProps> = ({ htmlCode, domPurifyConfig, parserOptions }) => {
const elements = useMemo(() => { const elements = useMemo(() => {
const sanitizedHtmlCode = measurePerformance('html-to-react: sanitize', () => { const sanitizedHtmlCode = measurePerformance('html-to-react: sanitize', () => {
return sanitize(htmlCode, { return DOMPurify.sanitize(htmlCode, {
...domPurifyConfig, ...domPurifyConfig,
RETURN_DOM_FRAGMENT: false, RETURN_DOM_FRAGMENT: false,
RETURN_DOM: false, RETURN_DOM: false,

View file

@ -1,19 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`IconButton correctly uses the onClick callback 1`] = ` exports[`IconButton > correctly uses the onClick callback 1`] = `
<div> <div>
<button <button
class="btn-icon d-inline-flex align-items-stretch btn btn-primary" class="_btn-icon_efc75b d-inline-flex align-items-stretch btn btn-primary"
data-testid="icon-button" data-testid="icon-button"
type="button" type="button"
> >
<span <span
class="icon-part" class="_icon-part_efc75b"
> >
BootstrapIconMock_Heart BootstrapIconMock_Heart
</span> </span>
<span <span
class="text-part" class="_text-part_efc75b"
> >
test with onClick test with onClick
</span> </span>
@ -21,20 +21,20 @@ exports[`IconButton correctly uses the onClick callback 1`] = `
</div> </div>
`; `;
exports[`IconButton renders heart icon 1`] = ` exports[`IconButton > renders heart icon 1`] = `
<div> <div>
<button <button
class="btn-icon d-inline-flex align-items-stretch btn btn-primary" class="_btn-icon_efc75b d-inline-flex align-items-stretch btn btn-primary"
data-testid="icon-button" data-testid="icon-button"
type="button" type="button"
> >
<span <span
class="icon-part" class="_icon-part_efc75b"
> >
BootstrapIconMock_Heart BootstrapIconMock_Heart
</span> </span>
<span <span
class="text-part" class="_text-part_efc75b"
> >
test test
</span> </span>
@ -42,20 +42,20 @@ exports[`IconButton renders heart icon 1`] = `
</div> </div>
`; `;
exports[`IconButton renders with additional className 1`] = ` exports[`IconButton > renders with additional className 1`] = `
<div> <div>
<button <button
class="btn-icon d-inline-flex align-items-stretch testClass btn btn-primary" class="_btn-icon_efc75b d-inline-flex align-items-stretch testClass btn btn-primary"
data-testid="icon-button" data-testid="icon-button"
type="button" type="button"
> >
<span <span
class="icon-part" class="_icon-part_efc75b"
> >
BootstrapIconMock_Heart BootstrapIconMock_Heart
</span> </span>
<span <span
class="text-part" class="_text-part_efc75b"
> >
test with additional className test with additional className
</span> </span>
@ -63,20 +63,20 @@ exports[`IconButton renders with additional className 1`] = `
</div> </div>
`; `;
exports[`IconButton renders with border 1`] = ` exports[`IconButton > renders with border 1`] = `
<div> <div>
<button <button
class="btn-icon d-inline-flex align-items-stretch with-border btn btn-primary" class="_btn-icon_efc75b d-inline-flex align-items-stretch _with-border_efc75b btn btn-primary"
data-testid="icon-button" data-testid="icon-button"
type="button" type="button"
> >
<span <span
class="icon-part" class="_icon-part_efc75b"
> >
BootstrapIconMock_Heart BootstrapIconMock_Heart
</span> </span>
<span <span
class="text-part" class="_text-part_efc75b"
> >
test with border test with border
</span> </span>

View file

@ -6,6 +6,7 @@
import { IconButton } from './icon-button' import { IconButton } from './icon-button'
import { fireEvent, render, screen } from '@testing-library/react' import { fireEvent, render, screen } from '@testing-library/react'
import { Heart as IconHeart } from 'react-bootstrap-icons' import { Heart as IconHeart } from 'react-bootstrap-icons'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('IconButton', () => { describe('IconButton', () => {
it('renders heart icon', () => { it('renders heart icon', () => {
@ -29,7 +30,7 @@ describe('IconButton', () => {
expect(view.container).toMatchSnapshot() expect(view.container).toMatchSnapshot()
}) })
it('correctly uses the onClick callback', async () => { it('correctly uses the onClick callback', async () => {
const onClick = jest.fn() const onClick = vitest.fn()
const view = render( const view = render(
<IconButton icon={IconHeart} onClick={onClick}> <IconButton icon={IconHeart} onClick={onClick}>
test with onClick test with onClick

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ExternalLink renders an external link correctly 1`] = ` exports[`ExternalLink > renders an external link correctly 1`] = `
<div> <div>
<a <a
class="" class=""
@ -14,7 +14,7 @@ exports[`ExternalLink renders an external link correctly 1`] = `
</div> </div>
`; `;
exports[`ExternalLink renders an external link with a title 1`] = ` exports[`ExternalLink > renders an external link with a title 1`] = `
<div> <div>
<a <a
class="" class=""
@ -29,7 +29,7 @@ exports[`ExternalLink renders an external link with a title 1`] = `
</div> </div>
`; `;
exports[`ExternalLink renders an external link with additional className 1`] = ` exports[`ExternalLink > renders an external link with additional className 1`] = `
<div> <div>
<a <a
class="testClass" class="testClass"
@ -43,7 +43,7 @@ exports[`ExternalLink renders an external link with additional className 1`] = `
</div> </div>
`; `;
exports[`ExternalLink renders an external link with an icon 1`] = ` exports[`ExternalLink > renders an external link with an icon 1`] = `
<div> <div>
<a <a
class="" class=""
@ -59,7 +59,7 @@ exports[`ExternalLink renders an external link with an icon 1`] = `
</div> </div>
`; `;
exports[`ExternalLink renders an external link with an id 1`] = ` exports[`ExternalLink > renders an external link with an id 1`] = `
<div> <div>
<a <a
class="" class=""

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`InternalLink renders an internal link correctly 1`] = ` exports[`InternalLink > renders an internal link correctly 1`] = `
<div> <div>
<a <a
class="" class=""
@ -11,7 +11,7 @@ exports[`InternalLink renders an internal link correctly 1`] = `
</div> </div>
`; `;
exports[`InternalLink renders an internal link with a title 1`] = ` exports[`InternalLink > renders an internal link with a title 1`] = `
<div> <div>
<a <a
class="" class=""
@ -23,7 +23,7 @@ exports[`InternalLink renders an internal link with a title 1`] = `
</div> </div>
`; `;
exports[`InternalLink renders an internal link with additional className 1`] = ` exports[`InternalLink > renders an internal link with additional className 1`] = `
<div> <div>
<a <a
class="testClass" class="testClass"
@ -34,7 +34,7 @@ exports[`InternalLink renders an internal link with additional className 1`] = `
</div> </div>
`; `;
exports[`InternalLink renders an internal link with an icon 1`] = ` exports[`InternalLink > renders an internal link with an icon 1`] = `
<div> <div>
<a <a
class="" class=""
@ -47,7 +47,7 @@ exports[`InternalLink renders an internal link with an icon 1`] = `
</div> </div>
`; `;
exports[`InternalLink renders an internal link with an id 1`] = ` exports[`InternalLink > renders an internal link with an id 1`] = `
<div> <div>
<a <a
class="" class=""

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`TranslatedExternalLink renders with i18nKey 1`] = ` exports[`TranslatedExternalLink > renders with i18nKey 1`] = `
<div> <div>
<a <a
class="" class=""

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`TranslatedInternalLink renders with i18nKey 1`] = ` exports[`TranslatedInternalLink > renders with i18nKey 1`] = `
<div> <div>
<a <a
class="" class=""

View file

@ -6,6 +6,7 @@
import { ExternalLink } from './external-link' import { ExternalLink } from './external-link'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { Heart as IconHeart } from 'react-bootstrap-icons' import { Heart as IconHeart } from 'react-bootstrap-icons'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('ExternalLink', () => { describe('ExternalLink', () => {
const href = 'https://example.com' const href = 'https://example.com'

View file

@ -6,6 +6,7 @@
import { InternalLink } from './internal-link' import { InternalLink } from './internal-link'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { Heart as IconHeart } from 'react-bootstrap-icons' import { Heart as IconHeart } from 'react-bootstrap-icons'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('InternalLink', () => { describe('InternalLink', () => {
const href = '/test' const href = '/test'

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { TranslatedExternalLink } from './translated-external-link' import { TranslatedExternalLink } from './translated-external-link'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('TranslatedExternalLink', () => { describe('TranslatedExternalLink', () => {
const href = 'https://example.com' const href = 'https://example.com'

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { TranslatedInternalLink } from './translated-internal-link' import { TranslatedInternalLink } from './translated-internal-link'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('TranslatedInternalLink', () => { describe('TranslatedInternalLink', () => {
const href = '/test' const href = '/test'

View file

@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`CommonModal does not render if show is false 1`] = `<div />`; exports[`CommonModal > does not render if show is false 1`] = `<div />`;
exports[`CommonModal render correctly in size lg 1`] = ` exports[`CommonModal > render correctly in size > lg 1`] = `
<div <div
class="modal-dialog modal-lg" class="modal-dialog modal-lg"
data-testid="commonModal" data-testid="commonModal"
@ -24,7 +24,7 @@ exports[`CommonModal render correctly in size lg 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly in size sm 1`] = ` exports[`CommonModal > render correctly in size > sm 1`] = `
<div <div
class="modal-dialog modal-sm" class="modal-dialog modal-sm"
data-testid="commonModal" data-testid="commonModal"
@ -46,7 +46,7 @@ exports[`CommonModal render correctly in size sm 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly in size xl 1`] = ` exports[`CommonModal > render correctly in size > xl 1`] = `
<div <div
class="modal-dialog modal-xl" class="modal-dialog modal-xl"
data-testid="commonModal" data-testid="commonModal"
@ -68,7 +68,7 @@ exports[`CommonModal render correctly in size xl 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly with additionalClasses 1`] = ` exports[`CommonModal > render correctly with additionalClasses 1`] = `
<div <div
class="modal-dialog testClass" class="modal-dialog testClass"
data-testid="commonModal" data-testid="commonModal"
@ -90,7 +90,7 @@ exports[`CommonModal render correctly with additionalClasses 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly with i18nTitle 1`] = ` exports[`CommonModal > render correctly with i18nTitle 1`] = `
<div <div
class="modal-dialog" class="modal-dialog"
data-testid="commonModal" data-testid="commonModal"
@ -112,7 +112,7 @@ exports[`CommonModal render correctly with i18nTitle 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly with title 1`] = ` exports[`CommonModal > render correctly with title 1`] = `
<div <div
class="modal-dialog" class="modal-dialog"
data-testid="commonModal" data-testid="commonModal"
@ -134,7 +134,7 @@ exports[`CommonModal render correctly with title 1`] = `
</div> </div>
`; `;
exports[`CommonModal render correctly with title icon 1`] = ` exports[`CommonModal > render correctly with title icon 1`] = `
<div <div
class="modal-dialog" class="modal-dialog"
data-testid="commonModal" data-testid="commonModal"
@ -158,7 +158,7 @@ exports[`CommonModal render correctly with title icon 1`] = `
</div> </div>
`; `;
exports[`CommonModal renders correctly and calls onHide, when close button is clicked 1`] = ` exports[`CommonModal > renders correctly and calls onHide, when close button is clicked 1`] = `
<div <div
class="modal-dialog" class="modal-dialog"
data-testid="commonModal" data-testid="commonModal"

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`DeletionModal renders correctly with deletionButtonI18nKey 1`] = ` exports[`DeletionModal > renders correctly with deletionButtonI18nKey 1`] = `
<div <div
class="modal-dialog" class="modal-dialog"
data-testid="commonModal" data-testid="commonModal"

View file

@ -8,11 +8,12 @@ import { CommonModal } from './common-modal'
import { fireEvent, render, screen } from '@testing-library/react' import { fireEvent, render, screen } from '@testing-library/react'
import React from 'react' import React from 'react'
import { Heart as IconHeart } from 'react-bootstrap-icons' import { Heart as IconHeart } from 'react-bootstrap-icons'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
describe('CommonModal', () => { describe('CommonModal', () => {
afterAll(() => { afterAll(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
beforeAll(async () => { beforeAll(async () => {
@ -25,7 +26,7 @@ describe('CommonModal', () => {
}) })
it('renders correctly and calls onHide, when close button is clicked', async () => { it('renders correctly and calls onHide, when close button is clicked', async () => {
const onHide = jest.fn() const onHide = vitest.fn()
render( render(
<CommonModal show={true} onHide={onHide} showCloseButton={true}> <CommonModal show={true} onHide={onHide} showCloseButton={true}>
testText testText

View file

@ -7,6 +7,7 @@ import { mockI18n } from '../../../test-utils/mock-i18n'
import { mockNotePermissions } from '../../../test-utils/mock-note-permissions' 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'
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
describe('DeletionModal', () => { describe('DeletionModal', () => {
beforeEach(async () => { beforeEach(async () => {
@ -14,13 +15,13 @@ describe('DeletionModal', () => {
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders correctly with deletionButtonI18nKey', async () => { it('renders correctly with deletionButtonI18nKey', async () => {
mockNotePermissions('test', 'test') mockNotePermissions('test', 'test')
const onConfirm = jest.fn() const onConfirm = vitest.fn()
render( render(
<DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}> <DeletionModal onConfirm={onConfirm} deletionButtonI18nKey={'testDeletionButton'} show={true}>
testText testText

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`create non existing note hint renders a waiting message when button is clicked 1`] = ` exports[`create non existing note hint > renders a waiting message when button is clicked 1`] = `
<div> <div>
<div <div
class="fade mt-5 alert alert-info show" class="fade mt-5 alert alert-info show"
@ -13,7 +13,7 @@ exports[`create non existing note hint renders a waiting message when button is
</div> </div>
`; `;
exports[`create non existing note hint renders an button as initial state 1`] = ` exports[`create non existing note hint > renders an button as initial state 1`] = `
<div> <div>
<div <div
class="fade mt-5 alert alert-info show" class="fade mt-5 alert alert-info show"
@ -38,9 +38,9 @@ exports[`create non existing note hint renders an button as initial state 1`] =
</div> </div>
`; `;
exports[`create non existing note hint renders nothing if no note id has been provided 1`] = `<div />`; exports[`create non existing note hint > renders nothing if no note id has been provided 1`] = `<div />`;
exports[`create non existing note hint shows an error message if note couldn't be created 1`] = ` exports[`create non existing note hint > shows an error message if note couldn't be created 1`] = `
<div> <div>
<div <div
class="fade mt-5 alert alert-danger show" class="fade mt-5 alert alert-danger show"
@ -53,7 +53,7 @@ exports[`create non existing note hint shows an error message if note couldn't b
</div> </div>
`; `;
exports[`create non existing note hint shows success message when the note has been created 1`] = ` exports[`create non existing note hint > shows success message when the note has been created 1`] = `
<div> <div>
<div <div
class="fade mt-5 alert alert-info show" class="fade mt-5 alert alert-info show"

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Note loading boundary loads a note 1`] = ` exports[`Note loading boundary > loads a note 1`] = `
<div> <div>
<span <span
data-testid="success" data-testid="success"
@ -10,7 +10,7 @@ exports[`Note loading boundary loads a note 1`] = `
</div> </div>
`; `;
exports[`Note loading boundary shows an error 1`] = ` exports[`Note loading boundary > shows an error 1`] = `
<div> <div>
<span <span
data-testid="CommonErrorPage" data-testid="CommonErrorPage"

View file

@ -10,15 +10,17 @@ import type { NoteDto, NoteMetadataDto } from '@hedgedoc/commons'
import { waitForOtherPromisesToFinish } from '@hedgedoc/commons' import { waitForOtherPromisesToFinish } from '@hedgedoc/commons'
import { act, render, screen, waitFor } from '@testing-library/react' import { act, render, screen, waitFor } from '@testing-library/react'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { afterEach, describe, expect, it, vitest, beforeAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../api/notes') vi.mock('../../../api/notes')
jest.mock('../../../hooks/common/use-single-string-url-parameter') vi.mock('../../../hooks/common/use-single-string-url-parameter')
describe('create non existing note hint', () => { describe('create non existing note hint', () => {
const mockedNoteId = 'mockedNoteId' const mockedNoteId = 'mockedNoteId'
const mockCreateNoteWithPrimaryAlias = () => { const mockCreateNoteWithPrimaryAlias = () => {
jest vi
.spyOn(createNoteWithPrimaryAliasModule, 'createNoteWithPrimaryAlias') .spyOn(createNoteWithPrimaryAliasModule, 'createNoteWithPrimaryAlias')
.mockImplementation(async (markdown, primaryAlias): Promise<NoteDto> => { .mockImplementation(async (markdown, primaryAlias): Promise<NoteDto> => {
expect(markdown).toBe('') expect(markdown).toBe('')
@ -31,7 +33,7 @@ describe('create non existing note hint', () => {
} }
const mockFailingCreateNoteWithPrimaryAlias = () => { const mockFailingCreateNoteWithPrimaryAlias = () => {
jest vi
.spyOn(createNoteWithPrimaryAliasModule, 'createNoteWithPrimaryAlias') .spyOn(createNoteWithPrimaryAliasModule, 'createNoteWithPrimaryAlias')
.mockImplementation(async (markdown, primaryAlias): Promise<NoteDto> => { .mockImplementation(async (markdown, primaryAlias): Promise<NoteDto> => {
expect(markdown).toBe('') expect(markdown).toBe('')
@ -46,12 +48,12 @@ describe('create non existing note hint', () => {
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders nothing if no note id has been provided', async () => { it('renders nothing if no note id has been provided', async () => {
const onNoteCreatedCallback = jest.fn() const onNoteCreatedCallback = vitest.fn()
const view = render( const view = render(
<CreateNonExistingNoteHint noteId={undefined} onNoteCreated={onNoteCreatedCallback}></CreateNonExistingNoteHint> <CreateNonExistingNoteHint noteId={undefined} onNoteCreated={onNoteCreatedCallback}></CreateNonExistingNoteHint>
) )
@ -62,7 +64,7 @@ describe('create non existing note hint', () => {
it('renders an button as initial state', async () => { it('renders an button as initial state', async () => {
mockCreateNoteWithPrimaryAlias() mockCreateNoteWithPrimaryAlias()
const onNoteCreatedCallback = jest.fn() const onNoteCreatedCallback = vitest.fn()
const view = render( const view = render(
<CreateNonExistingNoteHint <CreateNonExistingNoteHint
noteId={mockedNoteId} noteId={mockedNoteId}
@ -76,7 +78,7 @@ describe('create non existing note hint', () => {
it('renders a waiting message when button is clicked', async () => { it('renders a waiting message when button is clicked', async () => {
mockCreateNoteWithPrimaryAlias() mockCreateNoteWithPrimaryAlias()
const onNoteCreatedCallback = jest.fn() const onNoteCreatedCallback = vitest.fn()
const view = render( const view = render(
<CreateNonExistingNoteHint <CreateNonExistingNoteHint
noteId={mockedNoteId} noteId={mockedNoteId}
@ -96,7 +98,7 @@ describe('create non existing note hint', () => {
it('shows success message when the note has been created', async () => { it('shows success message when the note has been created', async () => {
mockCreateNoteWithPrimaryAlias() mockCreateNoteWithPrimaryAlias()
const onNoteCreatedCallback = jest.fn() const onNoteCreatedCallback = vitest.fn()
const view = render( const view = render(
<CreateNonExistingNoteHint <CreateNonExistingNoteHint
noteId={mockedNoteId} noteId={mockedNoteId}
@ -116,7 +118,7 @@ describe('create non existing note hint', () => {
it("shows an error message if note couldn't be created", async () => { it("shows an error message if note couldn't be created", async () => {
mockFailingCreateNoteWithPrimaryAlias() mockFailingCreateNoteWithPrimaryAlias()
const onNoteCreatedCallback = jest.fn() const onNoteCreatedCallback = vitest.fn()
const view = render( const view = render(
<CreateNonExistingNoteHint <CreateNonExistingNoteHint
noteId={mockedNoteId} noteId={mockedNoteId}

View file

@ -16,34 +16,36 @@ import { render, screen } from '@testing-library/react'
import { Fragment } from 'react' import { Fragment } from 'react'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import type { NoteDto } from '@hedgedoc/commons' import type { NoteDto } from '@hedgedoc/commons'
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../hooks/common/use-single-string-url-parameter') vi.mock('../../../hooks/common/use-single-string-url-parameter')
jest.mock('../../../api/notes') vi.mock('../../../api/notes')
jest.mock('../../../redux/note-details/methods') vi.mock('../../../redux/note-details/methods')
jest.mock('../../error-pages/common-error-page', () => ({ vi.mock('../../error-pages/common-error-page', () => ({
CommonErrorPage: jest.fn() CommonErrorPage: vitest.fn()
})) }))
jest.mock('../../../components/application-loader/loading-screen/loading-screen') vi.mock('../../../components/application-loader/loading-screen/loading-screen')
jest.mock('./create-non-existing-note-hint') vi.mock('./create-non-existing-note-hint')
describe('Note loading boundary', () => { describe('Note loading boundary', () => {
const mockedNoteId = 'mockedNoteId' const mockedNoteId = 'mockedNoteId'
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
beforeEach(async () => { beforeEach(async () => {
await mockI18n() await mockI18n()
jest.spyOn(CreateNonExistingNoteHintModule, 'CreateNonExistingNoteHint').mockImplementation(() => { vitest.spyOn(CreateNonExistingNoteHintModule, 'CreateNonExistingNoteHint').mockImplementation(() => {
return ( return (
<Fragment> <Fragment>
<span>This is a mock for CreateNonExistingNoteHint</span> <span>This is a mock for CreateNonExistingNoteHint</span>
</Fragment> </Fragment>
) )
}) })
jest.spyOn(LoadingScreenModule, 'LoadingScreen').mockImplementation(({ errorMessage }) => { vitest.spyOn(LoadingScreenModule, 'LoadingScreen').mockImplementation(({ errorMessage }) => {
return ( return (
<Fragment> <Fragment>
<span {...testId('LoadingScreen')}>This is a mock for LoadingScreen.</span> <span {...testId('LoadingScreen')}>This is a mock for LoadingScreen.</span>
@ -51,7 +53,7 @@ describe('Note loading boundary', () => {
</Fragment> </Fragment>
) )
}) })
jest vi
.spyOn(CommonErrorPageModule, 'CommonErrorPage') .spyOn(CommonErrorPageModule, 'CommonErrorPage')
.mockImplementation(({ titleI18nKey, descriptionI18nKey, children }) => { .mockImplementation(({ titleI18nKey, descriptionI18nKey, children }) => {
return ( return (
@ -66,7 +68,7 @@ describe('Note loading boundary', () => {
}) })
const mockGetNoteApiCall = (returnValue: NoteDto) => { const mockGetNoteApiCall = (returnValue: NoteDto) => {
jest.spyOn(getNoteModule, 'getNote').mockImplementation((id) => { vitest.spyOn(getNoteModule, 'getNote').mockImplementation((id) => {
expect(id).toBe(mockedNoteId) expect(id).toBe(mockedNoteId)
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(() => resolve(returnValue), 0) setTimeout(() => resolve(returnValue), 0)
@ -75,7 +77,7 @@ describe('Note loading boundary', () => {
} }
const mockCrashingNoteApiCall = () => { const mockCrashingNoteApiCall = () => {
jest.spyOn(getNoteModule, 'getNote').mockImplementation((id) => { vitest.spyOn(getNoteModule, 'getNote').mockImplementation((id) => {
expect(id).toBe(mockedNoteId) expect(id).toBe(mockedNoteId)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => reject(new ApiError(404, undefined, undefined)), 0) setTimeout(() => reject(new ApiError(404, undefined, undefined)), 0)
@ -83,8 +85,8 @@ describe('Note loading boundary', () => {
}) })
} }
const mockSetNoteInRedux = (expectedNote: NoteDto): jest.SpyInstance<void, [apiResponse: NoteDto]> => { const mockSetNoteInRedux = (expectedNote: NoteDto): vitest.SpyInstance<void, [apiResponse: NoteDto]> => {
return jest.spyOn(setNoteDataFromServerModule, 'setNoteDataFromServer').mockImplementation((givenNote) => { return vitest.spyOn(setNoteDataFromServerModule, 'setNoteDataFromServer').mockImplementation((givenNote) => {
expect(givenNote).toBe(expectedNote) expect(givenNote).toBe(expectedNote)
}) })
} }

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { createNumberRangeArray } from './number-range' import { createNumberRangeArray } from './number-range'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('number range', () => { describe('number range', () => {
it('creates an empty number range', () => { it('creates an empty number range', () => {

View file

@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`GuestUserAvatar renders the guest user avatar correctly 1`] = ` exports[`GuestUserAvatar > renders the guest user avatar correctly 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
BootstrapIconMock_Person BootstrapIconMock_Person
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
common.guestUser common.guestUser
</span> </span>

View file

@ -1,20 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`UserAvatar adds additionalClasses props to wrapping span 1`] = ` exports[`UserAvatar > adds additionalClasses props to wrapping span 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center testClass" class="d-inline-flex align-items-center testClass"
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="20" height="20"
src="https://example.com/test.png" src="https://example.com/test.png"
title="common.avatarOf" title="common.avatarOf"
width="20" width="20"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Boaty McBoatFace Boaty McBoatFace
</span> </span>
@ -22,14 +22,14 @@ exports[`UserAvatar adds additionalClasses props to wrapping span 1`] = `
</div> </div>
`; `;
exports[`UserAvatar does not show names if showName prop is false 1`] = ` exports[`UserAvatar > does not show names if showName prop is false 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="20" height="20"
src="https://example.com/test.png" src="https://example.com/test.png"
title="common.avatarOf" title="common.avatarOf"
@ -39,21 +39,21 @@ exports[`UserAvatar does not show names if showName prop is false 1`] = `
</div> </div>
`; `;
exports[`UserAvatar renders the user avatar correctly 1`] = ` exports[`UserAvatar > renders the user avatar correctly 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="20" height="20"
src="https://example.com/test.png" src="https://example.com/test.png"
title="common.avatarOf" title="common.avatarOf"
width="20" width="20"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Boaty McBoatFace Boaty McBoatFace
</span> </span>
@ -61,21 +61,21 @@ exports[`UserAvatar renders the user avatar correctly 1`] = `
</div> </div>
`; `;
exports[`UserAvatar renders the user avatar in size lg 1`] = ` exports[`UserAvatar > renders the user avatar in size > lg 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="30" height="30"
src="https://example.com/test.png" src="https://example.com/test.png"
title="common.avatarOf" title="common.avatarOf"
width="30" width="30"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Boaty McBoatFace Boaty McBoatFace
</span> </span>
@ -83,21 +83,21 @@ exports[`UserAvatar renders the user avatar in size lg 1`] = `
</div> </div>
`; `;
exports[`UserAvatar renders the user avatar in size sm 1`] = ` exports[`UserAvatar > renders the user avatar in size > sm 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="16" height="16"
src="https://example.com/test.png" src="https://example.com/test.png"
title="common.avatarOf" title="common.avatarOf"
width="16" width="16"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Boaty McBoatFace Boaty McBoatFace
</span> </span>
@ -105,7 +105,7 @@ exports[`UserAvatar renders the user avatar in size sm 1`] = `
</div> </div>
`; `;
exports[`UserAvatar uses custom photo component if provided 1`] = ` exports[`UserAvatar > uses custom photo component if provided 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
@ -114,7 +114,7 @@ exports[`UserAvatar uses custom photo component if provided 1`] = `
Custom Photo Custom Photo
</div> </div>
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
No face user No face user
</span> </span>
@ -122,7 +122,7 @@ exports[`UserAvatar uses custom photo component if provided 1`] = `
</div> </div>
`; `;
exports[`UserAvatar uses custom photo component preferred over photoUrl 1`] = ` exports[`UserAvatar > uses custom photo component preferred over photoUrl 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
@ -131,7 +131,7 @@ exports[`UserAvatar uses custom photo component preferred over photoUrl 1`] = `
Custom Photo Custom Photo
</div> </div>
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Boaty McBoatFace Boaty McBoatFace
</span> </span>
@ -139,21 +139,21 @@ exports[`UserAvatar uses custom photo component preferred over photoUrl 1`] = `
</div> </div>
`; `;
exports[`UserAvatar uses identicon when empty photoUrl is given 1`] = ` exports[`UserAvatar > uses identicon when empty photoUrl is given 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="20" height="20"
src="data:image/x-other,identicon-mock" src="data:image/x-other,identicon-mock"
title="common.avatarOf" title="common.avatarOf"
width="20" width="20"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
Empty Empty
</span> </span>
@ -161,21 +161,21 @@ exports[`UserAvatar uses identicon when empty photoUrl is given 1`] = `
</div> </div>
`; `;
exports[`UserAvatar uses identicon when no photoUrl is given 1`] = ` exports[`UserAvatar > uses identicon when no photoUrl is given 1`] = `
<div> <div>
<span <span
class="d-inline-flex align-items-center " class="d-inline-flex align-items-center "
> >
<img <img
alt="common.avatarOf" alt="common.avatarOf"
class="rounded user-image" class="rounded _user-image_b75d65"
height="20" height="20"
src="data:image/x-other,identicon-mock" src="data:image/x-other,identicon-mock"
title="common.avatarOf" title="common.avatarOf"
width="20" width="20"
/> />
<span <span
class="ms-2 me-1 user-line-name" class="ms-2 me-1 _user-line-name_b75d65"
> >
No face user No face user
</span> </span>

View file

@ -6,11 +6,13 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { GuestUserAvatar } from './guest-user-avatar' import { GuestUserAvatar } from './guest-user-avatar'
import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('@dicebear/identicon', () => null) vi.mock('@dicebear/identicon')
jest.mock('@dicebear/core', () => ({ vi.mock('@dicebear/core', () => ({
createAvatar: jest.fn(() => ({ createAvatar: vitest.fn(() => ({
toDataUri: jest.fn(() => 'data:image/x-other,identicon-mock') toDataUri: vitest.fn(() => 'data:image/x-other,identicon-mock')
})) }))
})) }))

View file

@ -7,11 +7,13 @@ import { mockI18n } from '../../../test-utils/mock-i18n'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { UserAvatar } from './user-avatar' import { UserAvatar } from './user-avatar'
import type { UserInfoDto } from '@hedgedoc/commons' import type { UserInfoDto } from '@hedgedoc/commons'
import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('@dicebear/identicon', () => null) vi.mock('@dicebear/identicon')
jest.mock('@dicebear/core', () => ({ vi.mock('@dicebear/core', () => ({
createAvatar: jest.fn(() => ({ createAvatar: vitest.fn(() => ({
toDataUri: jest.fn(() => 'data:image/x-other,identicon-mock') toDataUri: vitest.fn(() => 'data:image/x-other,identicon-mock')
})) }))
})) }))

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { findRegexMatchInText } from './find-regex-match-in-text' import { findRegexMatchInText } from './find-regex-match-in-text'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('find regex index in line', function () { describe('find regex index in line', function () {
it('finds the first occurrence', () => { it('finds the first occurrence', () => {

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { isCursorInCodeFence } from './codefenceDetection' import { isCursorInCodeFence } from './codefenceDetection'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Check whether cursor is in codefence', () => { describe('Check whether cursor is in codefence', () => {
it('returns false for empty document', () => { it('returns false for empty document', () => {

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { convertClipboardTableToMarkdown, isTable } from './table-extractor' import { convertClipboardTableToMarkdown, isTable } from './table-extractor'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('isTable detection: ', () => { describe('isTable detection: ', () => {
it('empty string is no table', () => { it('empty string is no table', () => {

View file

@ -9,8 +9,10 @@ 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' import { mockAppState } from '../../../../test-utils/mock-app-state'
import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll, MockInstance } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../hooks/common/use-application-state') vi.mock('../../../../hooks/common/use-application-state')
describe('use logout on user change', () => { describe('use logout on user change', () => {
const TestComponent: React.FC<{ messageTransporter: MessageTransporter }> = ({ messageTransporter }) => { const TestComponent: React.FC<{ messageTransporter: MessageTransporter }> = ({ messageTransporter }) => {
@ -24,11 +26,11 @@ describe('use logout on user change', () => {
}) })
} }
let disconnectCallback: jest.Mock let disconnectCallback: () => void
let messageTransporter: MessageTransporter let messageTransporter: MessageTransporter
beforeEach(() => { beforeEach(() => {
disconnectCallback = jest.fn() disconnectCallback = vi.fn()
messageTransporter = Mock.of<MessageTransporter>({ disconnect: disconnectCallback }) messageTransporter = Mock.of<MessageTransporter>({ disconnect: disconnectCallback })
}) })

View file

@ -7,38 +7,49 @@ import { FrontendWebsocketAdapter } from './frontend-websocket-adapter'
import type { Message } from '@hedgedoc/commons' import type { Message } from '@hedgedoc/commons'
import { ConnectionState, DisconnectReason, MessageType } from '@hedgedoc/commons' import { ConnectionState, DisconnectReason, MessageType } from '@hedgedoc/commons'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { describe, expect, it, vi, MockInstance, Mock as ViMock } from 'vitest'
interface MockedSocket {
addEventListenerSpy: ViMock
removeEventListenerSpy: ViMock
closeSpy: ViMock
sendSpy: ViMock
adapter: FrontendWebsocketAdapter
socket: WebSocket
}
describe('frontend websocket', () => { describe('frontend websocket', () => {
let addEventListenerSpy: jest.Mock function mockSocket(readyState: 0 | 1 | 2 | 3 = WebSocket.OPEN): MockedSocket {
let removeEventListenerSpy: jest.Mock const addEventListenerSpy = vi.fn()
let closeSpy: jest.Mock const removeEventListenerSpy = vi.fn()
let sendSpy: jest.Mock const closeSpy = vi.fn()
let adapter: FrontendWebsocketAdapter const sendSpy = vi.fn()
let mockedSocket: WebSocket
function mockSocket(readyState: 0 | 1 | 2 | 3 = WebSocket.OPEN) { const socket = Mock.of<WebSocket>({
addEventListenerSpy = jest.fn()
removeEventListenerSpy = jest.fn()
closeSpy = jest.fn()
sendSpy = jest.fn()
mockedSocket = Mock.of<WebSocket>({
addEventListener: addEventListenerSpy, addEventListener: addEventListenerSpy,
removeEventListener: removeEventListenerSpy, removeEventListener: removeEventListenerSpy,
close: closeSpy, close: closeSpy,
send: sendSpy, send: sendSpy,
readyState: readyState readyState: readyState
}) })
adapter = new FrontendWebsocketAdapter(mockedSocket) const adapter = new FrontendWebsocketAdapter(socket)
return {
adapter,
addEventListenerSpy,
removeEventListenerSpy,
closeSpy,
sendSpy,
socket
}
} }
it('can bind and unbind the close event', () => { it('can bind and unbind the close event', () => {
mockSocket() const { adapter, socket, removeEventListenerSpy } = mockSocket()
const handler = jest.fn((reason?: DisconnectReason) => console.log(reason)) const handler = vi.fn((reason?: DisconnectReason) => console.log(reason))
let modifiedHandler: EventListenerOrEventListenerObject = jest.fn() let modifiedHandler: EventListenerOrEventListenerObject = vi.fn()
jest.spyOn(mockedSocket, 'addEventListener').mockImplementation((event, handler_) => { vi.spyOn(socket, 'addEventListener').mockImplementation((event, handler_) => {
modifiedHandler = handler_ modifiedHandler = handler_
}) })
@ -54,8 +65,8 @@ describe('frontend websocket', () => {
}) })
it('can bind and unbind the connect event', () => { it('can bind and unbind the connect event', () => {
mockSocket() const { adapter, addEventListenerSpy, removeEventListenerSpy } = mockSocket()
const handler = jest.fn() const handler = vi.fn()
const unbind = adapter.bindOnConnectedEvent(handler) const unbind = adapter.bindOnConnectedEvent(handler)
expect(addEventListenerSpy).toHaveBeenCalledWith('open', handler) expect(addEventListenerSpy).toHaveBeenCalledWith('open', handler)
unbind() unbind()
@ -63,8 +74,8 @@ describe('frontend websocket', () => {
}) })
it('can bind and unbind the error event', () => { it('can bind and unbind the error event', () => {
mockSocket() const { adapter, addEventListenerSpy, removeEventListenerSpy } = mockSocket()
const handler = jest.fn() const handler = vi.fn()
const unbind = adapter.bindOnErrorEvent(handler) const unbind = adapter.bindOnErrorEvent(handler)
expect(addEventListenerSpy).toHaveBeenCalledWith('error', handler) expect(addEventListenerSpy).toHaveBeenCalledWith('error', handler)
unbind() unbind()
@ -72,11 +83,11 @@ describe('frontend websocket', () => {
}) })
it('can bind, unbind and translate the message event', () => { it('can bind, unbind and translate the message event', () => {
mockSocket() const { adapter, socket, addEventListenerSpy, removeEventListenerSpy } = mockSocket()
const handler = jest.fn() const handler = vi.fn()
let modifiedHandler: EventListenerOrEventListenerObject = jest.fn() let modifiedHandler: EventListenerOrEventListenerObject = vi.fn()
jest.spyOn(mockedSocket, 'addEventListener').mockImplementation((event, handler_) => { addEventListenerSpy.mockImplementation((event, handler_) => {
modifiedHandler = handler_ modifiedHandler = handler_
}) })
@ -94,35 +105,35 @@ describe('frontend websocket', () => {
}) })
it('can disconnect the socket', () => { it('can disconnect the socket', () => {
mockSocket() const { adapter, closeSpy } = mockSocket()
adapter.disconnect() adapter.disconnect()
expect(closeSpy).toHaveBeenCalled() expect(closeSpy).toHaveBeenCalled()
}) })
it('can send messages', () => { it('can send messages', () => {
mockSocket() const { adapter, sendSpy } = mockSocket()
const value: Message<MessageType> = { type: MessageType.READY_REQUEST } const value: Message<MessageType> = { type: MessageType.READY_REQUEST }
adapter.send(value) adapter.send(value)
expect(sendSpy).toHaveBeenCalledWith('{"type":"READY_REQUEST"}') expect(sendSpy).toHaveBeenCalledWith('{"type":"READY_REQUEST"}')
}) })
it('can read the connection state when open', () => { it('can read the connection state when open', () => {
mockSocket(WebSocket.OPEN) const { adapter } = mockSocket(WebSocket.OPEN)
expect(adapter.getConnectionState()).toBe(ConnectionState.CONNECTED) expect(adapter.getConnectionState()).toBe(ConnectionState.CONNECTED)
}) })
it('can read the connection state when connecting', () => { it('can read the connection state when connecting', () => {
mockSocket(WebSocket.CONNECTING) const { adapter } = mockSocket(WebSocket.CONNECTING)
expect(adapter.getConnectionState()).toBe(ConnectionState.CONNECTING) expect(adapter.getConnectionState()).toBe(ConnectionState.CONNECTING)
}) })
it('can read the connection state when closing', () => { it('can read the connection state when closing', () => {
mockSocket(WebSocket.CLOSING) const { adapter } = mockSocket(WebSocket.CLOSING)
expect(adapter.getConnectionState()).toBe(ConnectionState.DISCONNECTED) expect(adapter.getConnectionState()).toBe(ConnectionState.DISCONNECTED)
}) })
it('can read the connection state when closed', () => { it('can read the connection state when closed', () => {
mockSocket(WebSocket.CLOSED) const { adapter } = mockSocket(WebSocket.CLOSED)
expect(adapter.getConnectionState()).toBe(ConnectionState.DISCONNECTED) expect(adapter.getConnectionState()).toBe(ConnectionState.DISCONNECTED)
}) })
}) })

View file

@ -8,6 +8,7 @@ import { FrontmatterLinter } from './frontmatter-linter'
import { mockEditorView } from './single-line-regex-linter.spec' import { mockEditorView } from './single-line-regex-linter.spec'
import type { Diagnostic } from '@codemirror/lint' import type { Diagnostic } from '@codemirror/lint'
import { t } from 'i18next' import { t } from 'i18next'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
const testFrontmatterLinter = ( const testFrontmatterLinter = (
editorContent: string, editorContent: string,
@ -22,7 +23,7 @@ const testFrontmatterLinter = (
expect(calculatedDiagnostics[0].to).toEqual(expectedDiagnostics.to) expect(calculatedDiagnostics[0].to).toEqual(expectedDiagnostics.to)
expect(calculatedDiagnostics[0].severity).toEqual(expectedDiagnostics.severity) expect(calculatedDiagnostics[0].severity).toEqual(expectedDiagnostics.severity)
if (expectedReplacement !== undefined) { if (expectedReplacement !== undefined) {
const spy = jest.spyOn(editorView, 'dispatch') const spy = vitest.spyOn(editorView, 'dispatch')
expect(calculatedDiagnostics[0].actions).toHaveLength(1) expect(calculatedDiagnostics[0].actions).toHaveLength(1)
expect(calculatedDiagnostics[0].actions?.[0].name).toEqual(t('editor.linter.defaultAction')) expect(calculatedDiagnostics[0].actions?.[0].name).toEqual(t('editor.linter.defaultAction'))
calculatedDiagnostics[0].actions?.[0].apply(editorView, calculatedDiagnostics[0].from, calculatedDiagnostics[0].to) calculatedDiagnostics[0].actions?.[0].apply(editorView, calculatedDiagnostics[0].from, calculatedDiagnostics[0].to)

View file

@ -9,6 +9,7 @@ import type { Diagnostic } from '@codemirror/lint'
import type { EditorState, Text } from '@codemirror/state' import type { EditorState, Text } from '@codemirror/state'
import type { EditorView } from '@codemirror/view' import type { EditorView } from '@codemirror/view'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
export const mockEditorView = (content: string): EditorView => { export const mockEditorView = (content: string): EditorView => {
const docMock = Mock.of<Text>() const docMock = Mock.of<Text>()
@ -17,7 +18,7 @@ export const mockEditorView = (content: string): EditorView => {
state: Mock.of<EditorState>({ state: Mock.of<EditorState>({
doc: docMock doc: docMock
}), }),
dispatch: jest.fn() dispatch: vitest.fn()
}) })
} }

View file

@ -5,6 +5,7 @@
*/ */
import { addLink } from './add-link' import { addLink } from './add-link'
import type { ContentEdits } from './types/changes' import type { ContentEdits } from './types/changes'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('add link', () => { describe('add link', () => {
describe('without to-cursor', () => { describe('without to-cursor', () => {

View file

@ -5,6 +5,7 @@
*/ */
import { prependLinesOfSelection } from './prepend-lines-of-selection' import { prependLinesOfSelection } from './prepend-lines-of-selection'
import type { ContentEdits } from './types/changes' import type { ContentEdits } from './types/changes'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('replace lines of selection', () => { describe('replace lines of selection', () => {
it('replaces only the from-cursor line if no to-cursor is present', () => { it('replaces only the from-cursor line if no to-cursor is present', () => {

View file

@ -5,6 +5,7 @@
*/ */
import { replaceSelection } from './replace-selection' import { replaceSelection } from './replace-selection'
import type { ContentEdits } from './types/changes' import type { ContentEdits } from './types/changes'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('replace selection', () => { describe('replace selection', () => {
it('inserts a text after the from-cursor if no to-cursor is present', () => { it('inserts a text after the from-cursor if no to-cursor is present', () => {

View file

@ -9,6 +9,7 @@ import {
searchForEndOfLine, searchForEndOfLine,
searchForStartOfLine searchForStartOfLine
} from './change-cursors-to-whole-line-if-no-to-cursor' } from './change-cursors-to-whole-line-if-no-to-cursor'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('changeCursorsToWholeLineIfNoToCursor', () => { describe('changeCursorsToWholeLineIfNoToCursor', () => {
it(`returns the given selection if to cursor is present`, () => { it(`returns the given selection if to cursor is present`, () => {

View file

@ -5,6 +5,7 @@
*/ */
import type { ContentEdits } from './types/changes' import type { ContentEdits } from './types/changes'
import { wrapSelection } from './wrap-selection' import { wrapSelection } from './wrap-selection'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('wrap selection', () => { describe('wrap selection', () => {
it(`doesn't modify any line if no to-cursor is present`, () => { it(`doesn't modify any line if no to-cursor is present`, () => {

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { createMarkdownTable } from './create-markdown-table' import { createMarkdownTable } from './create-markdown-table'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('create markdown table', () => { describe('create markdown table', () => {
it('generates a valid table', () => { it('generates a valid table', () => {

View file

@ -6,6 +6,7 @@
import { extractSelectedText } from './extract-selected-text' import { extractSelectedText } from './extract-selected-text'
import type { EditorState, SelectionRange } from '@codemirror/state' import type { EditorState, SelectionRange } from '@codemirror/state'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('extract selected text', () => { describe('extract selected text', () => {
const mockContent = "I'm a mock content!" const mockContent = "I'm a mock content!"

View file

@ -8,9 +8,11 @@ import * as UseNoteMarkdownContent from '../../../../hooks/common/use-note-markd
import { useHasMarkdownContentBeenChangedInBackground } from './use-has-markdown-content-been-changed-in-background' import { useHasMarkdownContentBeenChangedInBackground } from './use-has-markdown-content-been-changed-in-background'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import React, { Fragment } from 'react' import React, { Fragment } from 'react'
import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../hooks/common/use-is-document-visible') vi.mock('../../../../hooks/common/use-is-document-visible')
jest.mock('../../../../hooks/common/use-note-markdown-content') vi.mock('../../../../hooks/common/use-note-markdown-content')
describe('use has markdown content been changed in background', () => { describe('use has markdown content been changed in background', () => {
const TestComponent: React.FC = () => { const TestComponent: React.FC = () => {
@ -22,8 +24,8 @@ describe('use has markdown content been changed in background', () => {
let noteContent = 'content' let noteContent = 'content'
beforeEach(() => { beforeEach(() => {
jest.spyOn(UseIsDocumentVisibleModule, 'useIsDocumentVisible').mockImplementation(() => documentVisible) vitest.spyOn(UseIsDocumentVisibleModule, 'useIsDocumentVisible').mockImplementation(() => documentVisible)
jest.spyOn(UseNoteMarkdownContent, 'useNoteMarkdownContent').mockImplementation(() => noteContent) vitest.spyOn(UseNoteMarkdownContent, 'useNoteMarkdownContent').mockImplementation(() => noteContent)
}) })
it('returns the correct value', () => { it('returns the correct value', () => {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`realtime connection alert will render correctly 1`] = ` exports[`realtime connection alert > will render correctly 1`] = `
<div> <div>
<div <div
class="fade w-100 m-0 px-2 py-1 border-top-0 border-bottom-0 d-flex align-items-center alert alert-warning show" class="fade w-100 m-0 px-2 py-1 border-top-0 border-bottom-0 d-flex align-items-center alert alert-warning show"

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../test-utils/mock-i18n' import { mockI18n } from '../../../test-utils/mock-i18n'
import { RealtimeConnectionAlert } from './realtime-connection-alert' import { RealtimeConnectionAlert } from './realtime-connection-alert'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll } from 'vitest'
describe('realtime connection alert', () => { describe('realtime connection alert', () => {
beforeAll(mockI18n) beforeAll(mockI18n)

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AliasesAddForm renders the input form 1`] = ` exports[`AliasesAddForm > renders the input form 1`] = `
<div> <div>
<form> <form>
<div <div

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AliasesListEntry adds aliasPrimaryBadge & removes aliasButtonMakePrimary in AliasesListEntry if it's primary 1`] = ` exports[`AliasesListEntry > adds aliasPrimaryBadge & removes aliasButtonMakePrimary in AliasesListEntry if it's primary 1`] = `
<div> <div>
<li <li
class="list-group-item d-flex flex-row justify-content-between align-items-center" class="list-group-item d-flex flex-row justify-content-between align-items-center"
@ -30,7 +30,7 @@ exports[`AliasesListEntry adds aliasPrimaryBadge & removes aliasButtonMakePrimar
</div> </div>
`; `;
exports[`AliasesListEntry removes aliasPrimaryBadge & adds aliasButtonMakePrimary in AliasesListEntry if it's not primary 1`] = ` exports[`AliasesListEntry > removes aliasPrimaryBadge & adds aliasButtonMakePrimary in AliasesListEntry if it's not primary 1`] = `
<div> <div>
<li <li
class="list-group-item d-flex flex-row justify-content-between align-items-center" class="list-group-item d-flex flex-row justify-content-between align-items-center"
@ -62,7 +62,7 @@ exports[`AliasesListEntry removes aliasPrimaryBadge & adds aliasButtonMakePrimar
</div> </div>
`; `;
exports[`AliasesListEntry renders an AliasesListEntry that is not primary 1`] = ` exports[`AliasesListEntry > renders an AliasesListEntry that is not primary 1`] = `
<div> <div>
<li <li
class="list-group-item d-flex flex-row justify-content-between align-items-center" class="list-group-item d-flex flex-row justify-content-between align-items-center"
@ -92,7 +92,7 @@ exports[`AliasesListEntry renders an AliasesListEntry that is not primary 1`] =
</div> </div>
`; `;
exports[`AliasesListEntry renders an AliasesListEntry that is primary 1`] = ` exports[`AliasesListEntry > renders an AliasesListEntry that is primary 1`] = `
<div> <div>
<li <li
class="list-group-item d-flex flex-row justify-content-between align-items-center" class="list-group-item d-flex flex-row justify-content-between align-items-center"

View file

@ -1,27 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AliasesList renders the AliasList sorted 1`] = ` exports[`AliasesList > renders the AliasList sorted 1`] = `<div />`;
<div>
<span>
Alias:
a-test
(
non-primary
)
</span>
<span>
Alias:
b-test
(
primary
)
</span>
<span>
Alias:
z-test
(
non-primary
)
</span>
</div>
`;

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AliasesModal renders the modal 1`] = ` exports[`AliasesModal > renders the modal 1`] = `
<div> <div>
<span> <span>
This is a mock implementation of a Modal: This is a mock implementation of a Modal:

View file

@ -13,11 +13,15 @@ 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' import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
import { beforeEach, describe, expect, it, vitest, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../../../api/alias') vi.mock('../../../../../../api/alias')
jest.mock('../../../../../../redux/note-details/methods') vi.mock('../../../../../../redux/note-details/methods')
jest.mock('../../../../../../hooks/common/use-application-state') vi.mock('../../../../../../hooks/common/use-application-state')
jest.mock('../../../../../notifications/ui-notification-boundary') vi.mock('../../../../../notifications/ui-notification-boundary', () => ({
useUiNotifications: vi.fn(() => ({ showErrorNotification: vi.fn() }))
}))
const addPromise = Promise.resolve({ name: 'mock', primaryAlias: true, noteId: 'mock' }) const addPromise = Promise.resolve({ name: 'mock', primaryAlias: true, noteId: 'mock' })
@ -25,14 +29,14 @@ describe('AliasesAddForm', () => {
beforeEach(async () => { beforeEach(async () => {
await mockI18n() await mockI18n()
mockUiNotifications() mockUiNotifications()
jest.spyOn(AliasModule, 'addAlias').mockImplementation(() => addPromise) vitest.spyOn(AliasModule, 'addAlias').mockImplementation(() => addPromise)
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve()) vitest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
mockNotePermissions('test', 'test', undefined, { noteDetails: { id: 'mock-note' } as NoteDetails }) mockNotePermissions('test', 'test', undefined, { noteDetails: { id: 'mock-note' } as NoteDetails })
}) })
afterAll(() => { afterAll(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders the input form', async () => { it('renders the input form', async () => {

View file

@ -3,8 +3,6 @@
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import * as AliasModule from '../../../../../../api/alias'
import * as NoteDetailsReduxModule from '../../../../../../redux/note-details/methods'
import { mockI18n } from '../../../../../../test-utils/mock-i18n' import { mockI18n } from '../../../../../../test-utils/mock-i18n'
import { mockNotePermissions } from '../../../../../../test-utils/mock-note-permissions' import { mockNotePermissions } from '../../../../../../test-utils/mock-note-permissions'
import { AliasesListEntry } from './aliases-list-entry' import { AliasesListEntry } from './aliases-list-entry'
@ -12,27 +10,36 @@ import { act, render, screen } from '@testing-library/react'
import React from 'react' import React from 'react'
import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications' import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
import type { AliasDto } from '@hedgedoc/commons' import type { AliasDto } from '@hedgedoc/commons'
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../../../api/alias') const { updateMetadata, markAliasAsPrimary, deleteAlias } = vi.hoisted(() => ({
jest.mock('../../../../../../redux/note-details/methods') deleteAlias: vi.fn(() => Promise.resolve()),
jest.mock('../../../../../notifications/ui-notification-boundary') markAliasAsPrimary: vi.fn(() => Promise.resolve({ name: 'mock', primaryAlias: true, noteId: 'mock' })),
jest.mock('../../../../../../hooks/common/use-application-state') updateMetadata: vi.fn(() => Promise.resolve())
}))
const deletePromise = Promise.resolve() vi.mock('../../../../../../api/alias', () => ({
const markAsPrimaryPromise = Promise.resolve({ name: 'mock', primaryAlias: true, noteId: 'mock' }) deleteAlias,
markAliasAsPrimary
}))
vi.mock('../../../../../../redux/note-details/methods', () => ({
updateMetadata
}))
vi.mock('../../../../../notifications/ui-notification-boundary', () => ({
useUiNotifications: vi.fn(() => ({ showErrorNotification: vi.fn() }))
}))
vi.mock('../../../../../../hooks/common/use-application-state')
describe('AliasesListEntry', () => { describe('AliasesListEntry', () => {
beforeEach(async () => { beforeEach(async () => {
await mockI18n() await mockI18n()
mockUiNotifications() mockUiNotifications()
jest.spyOn(AliasModule, 'deleteAlias').mockImplementation(() => deletePromise)
jest.spyOn(AliasModule, 'markAliasAsPrimary').mockImplementation(() => markAsPrimaryPromise)
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders an AliasesListEntry that is primary', async () => { it('renders an AliasesListEntry that is primary', async () => {
@ -48,9 +55,8 @@ describe('AliasesListEntry', () => {
await act<void>(() => { await act<void>(() => {
button.click() button.click()
}) })
expect(AliasModule.deleteAlias).toBeCalledWith(testAlias.name) expect(deleteAlias).toBeCalledWith(testAlias.name)
await deletePromise expect(updateMetadata).toBeCalled()
expect(NoteDetailsReduxModule.updateMetadata).toBeCalled()
}) })
it("adds aliasPrimaryBadge & removes aliasButtonMakePrimary in AliasesListEntry if it's primary", () => { it("adds aliasPrimaryBadge & removes aliasButtonMakePrimary in AliasesListEntry if it's primary", () => {
@ -77,16 +83,14 @@ describe('AliasesListEntry', () => {
await act<void>(() => { await act<void>(() => {
buttonRemove.click() buttonRemove.click()
}) })
expect(AliasModule.deleteAlias).toBeCalledWith(testAlias.name) expect(deleteAlias).toBeCalledWith(testAlias.name)
await deletePromise expect(updateMetadata).toBeCalled()
expect(NoteDetailsReduxModule.updateMetadata).toBeCalled()
const buttonMakePrimary = await screen.findByTestId('aliasButtonMakePrimary') const buttonMakePrimary = await screen.findByTestId('aliasButtonMakePrimary')
await act<void>(() => { await act<void>(() => {
buttonMakePrimary.click() buttonMakePrimary.click()
}) })
expect(AliasModule.markAliasAsPrimary).toBeCalledWith(testAlias.name) expect(markAliasAsPrimary).toBeCalledWith(testAlias.name)
await markAsPrimaryPromise expect(updateMetadata).toBeCalled()
expect(NoteDetailsReduxModule.updateMetadata).toBeCalled()
}) })
it("removes aliasPrimaryBadge & adds aliasButtonMakePrimary in AliasesListEntry if it's not primary", () => { it("removes aliasPrimaryBadge & adds aliasButtonMakePrimary in AliasesListEntry if it's not primary", () => {

View file

@ -10,9 +10,11 @@ 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' import { mockAppState } from '../../../../../../test-utils/mock-app-state'
import { beforeEach, describe, expect, it, vitest, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../../../hooks/common/use-application-state') vi.mock('../../../../../../hooks/common/use-application-state')
jest.mock('./aliases-list-entry') vi.mock('./aliases-list-entry')
describe('AliasesList', () => { describe('AliasesList', () => {
beforeEach(async () => { beforeEach(async () => {
@ -38,7 +40,7 @@ describe('AliasesList', () => {
] ]
} }
}) })
jest.spyOn(AliasesListEntryModule, 'AliasesListEntry').mockImplementation((({ alias }) => { vitest.spyOn(AliasesListEntryModule, 'AliasesListEntry').mockImplementation((({ alias }) => {
return ( return (
<span> <span>
Alias: {alias.name} ({alias.primaryAlias ? 'primary' : 'non-primary'}) Alias: {alias.name} ({alias.primaryAlias ? 'primary' : 'non-primary'})
@ -48,8 +50,8 @@ describe('AliasesList', () => {
}) })
afterAll(() => { afterAll(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders the AliasList sorted', () => { it('renders the AliasList sorted', () => {

View file

@ -13,34 +13,36 @@ 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' import { mockUiNotifications } from '../../../../../../test-utils/mock-ui-notifications'
import { beforeEach, describe, expect, it, vitest, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('./aliases-list') vi.mock('./aliases-list')
jest.mock('./aliases-add-form') vi.mock('./aliases-add-form')
jest.mock('../../../../../common/modals/common-modal') vi.mock('../../../../../common/modals/common-modal')
jest.mock('../../../../../notifications/ui-notification-boundary') vi.mock('../../../../../notifications/ui-notification-boundary')
describe('AliasesModal', () => { describe('AliasesModal', () => {
beforeEach(async () => { beforeEach(async () => {
await mockI18n() await mockI18n()
mockUiNotifications() mockUiNotifications()
jest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children }) => { vitest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children }) => {
return ( return (
<span> <span>
This is a mock implementation of a Modal: <dialog>{children}</dialog> This is a mock implementation of a Modal: <dialog>{children}</dialog>
</span> </span>
) )
}) as React.FC<PropsWithChildren<CommonModalProps>>) }) as React.FC<PropsWithChildren<CommonModalProps>>)
jest.spyOn(AliasesListModule, 'AliasesList').mockImplementation((() => { vitest.spyOn(AliasesListModule, 'AliasesList').mockImplementation((() => {
return <span>This is a mock for the AliasesList that is tested separately.</span> return <span>This is a mock for the AliasesList that is tested separately.</span>
}) as React.FC) }) as React.FC)
jest.spyOn(AliasesAddFormModule, 'AliasesAddForm').mockImplementation((() => { vitest.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)
}) })
afterAll(() => { afterAll(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders the modal', () => { it('renders the modal', () => {

View file

@ -1,4 +1,5 @@
import { validateToken } from './validate-token' import { validateToken } from './validate-token'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
/* /*
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`invert unified patch inverts a patch correctly 1`] = ` exports[`invert unified patch > inverts a patch correctly 1`] = `
{ {
"hunks": [ "hunks": [
{ {

View file

@ -5,6 +5,7 @@
*/ */
import { invertUnifiedPatch } from './invert-unified-patch' import { invertUnifiedPatch } from './invert-unified-patch'
import { parsePatch } from 'diff' import { parsePatch } from 'diff'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('invert unified patch', () => { describe('invert unified patch', () => {
it('inverts a patch correctly', () => { it('inverts a patch correctly', () => {

View file

@ -1,31 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Splitter resize can change size with mouse 1`] = ` exports[`Splitter > resize > can change size with mouse 1`] = `
<div> <div>
<div <div
class="flex-fill flex-row d-flex " class="flex-fill flex-row d-flex "
> >
<div <div
class="left" class="_left_d43a0d"
id="editor-edit-pane" id="editor-edit-pane"
style="width: calc(50% - 5px);" style="width: calc(-5px + (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
left left
</div> </div>
</div> </div>
<div <div
class="divider" class="_divider_e4e78e"
data-testid="splitter-divider" data-testid="splitter-divider"
id="editor-splitter" id="editor-splitter"
> >
<div <div
class="middle" class="_middle_e4e78e"
> >
<div <div
class="buttons" class="_buttons_e4e78e"
> >
<button <button
class="btn btn-light" class="btn btn-light"
@ -34,7 +34,7 @@ exports[`Splitter resize can change size with mouse 1`] = `
BootstrapIconMock_ArrowLeft BootstrapIconMock_ArrowLeft
</button> </button>
<span <span
class="grabber" class="_grabber_e4e78e"
> >
BootstrapIconMock_ArrowLeftRight BootstrapIconMock_ArrowLeftRight
</span> </span>
@ -48,12 +48,12 @@ exports[`Splitter resize can change size with mouse 1`] = `
</div> </div>
</div> </div>
<div <div
class="right" class="_right_d43a0d"
id="editor-view-pane" id="editor-view-pane"
style="width: calc(100% - 50%);" style="width: calc(100% - (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
right right
</div> </div>
@ -62,32 +62,32 @@ exports[`Splitter resize can change size with mouse 1`] = `
</div> </div>
`; `;
exports[`Splitter resize can change size with touch 1`] = ` exports[`Splitter > resize > can change size with touch 1`] = `
<div> <div>
<div <div
class="flex-fill flex-row d-flex " class="flex-fill flex-row d-flex "
> >
<div <div
class="left" class="_left_d43a0d"
id="editor-edit-pane" id="editor-edit-pane"
style="width: calc(50% - 5px);" style="width: calc(-5px + (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
left left
</div> </div>
</div> </div>
<div <div
class="divider" class="_divider_e4e78e"
data-testid="splitter-divider" data-testid="splitter-divider"
id="editor-splitter" id="editor-splitter"
> >
<div <div
class="middle" class="_middle_e4e78e"
> >
<div <div
class="buttons" class="_buttons_e4e78e"
> >
<button <button
class="btn btn-light" class="btn btn-light"
@ -96,7 +96,7 @@ exports[`Splitter resize can change size with touch 1`] = `
BootstrapIconMock_ArrowLeft BootstrapIconMock_ArrowLeft
</button> </button>
<span <span
class="grabber" class="_grabber_e4e78e"
> >
BootstrapIconMock_ArrowLeftRight BootstrapIconMock_ArrowLeftRight
</span> </span>
@ -110,12 +110,12 @@ exports[`Splitter resize can change size with touch 1`] = `
</div> </div>
</div> </div>
<div <div
class="right" class="_right_d43a0d"
id="editor-view-pane" id="editor-view-pane"
style="width: calc(100% - 50%);" style="width: calc(100% - (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
right right
</div> </div>
@ -124,32 +124,32 @@ exports[`Splitter resize can change size with touch 1`] = `
</div> </div>
`; `;
exports[`Splitter resize can change size with touch 2`] = ` exports[`Splitter > resize > can change size with touch 2`] = `
<div> <div>
<div <div
class="flex-fill flex-row d-flex " class="flex-fill flex-row d-flex "
> >
<div <div
class="left" class="_left_d43a0d"
id="editor-edit-pane" id="editor-edit-pane"
style="width: calc(50% - 5px);" style="width: calc(-5px + (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
left left
</div> </div>
</div> </div>
<div <div
class="divider" class="_divider_e4e78e"
data-testid="splitter-divider" data-testid="splitter-divider"
id="editor-splitter" id="editor-splitter"
> >
<div <div
class="middle" class="_middle_e4e78e"
> >
<div <div
class="buttons" class="_buttons_e4e78e"
> >
<button <button
class="btn btn-light" class="btn btn-light"
@ -158,7 +158,7 @@ exports[`Splitter resize can change size with touch 2`] = `
BootstrapIconMock_ArrowLeft BootstrapIconMock_ArrowLeft
</button> </button>
<span <span
class="grabber" class="_grabber_e4e78e"
> >
BootstrapIconMock_ArrowLeftRight BootstrapIconMock_ArrowLeftRight
</span> </span>
@ -172,12 +172,12 @@ exports[`Splitter resize can change size with touch 2`] = `
</div> </div>
</div> </div>
<div <div
class="right" class="_right_d43a0d"
id="editor-view-pane" id="editor-view-pane"
style="width: calc(100% - 50%);" style="width: calc(100% - (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
right right
</div> </div>
@ -186,32 +186,32 @@ exports[`Splitter resize can change size with touch 2`] = `
</div> </div>
`; `;
exports[`Splitter resize can change size with touch 3`] = ` exports[`Splitter > resize > can change size with touch 3`] = `
<div> <div>
<div <div
class="flex-fill flex-row d-flex " class="flex-fill flex-row d-flex "
> >
<div <div
class="left" class="_left_d43a0d"
id="editor-edit-pane" id="editor-edit-pane"
style="width: calc(50% - 5px);" style="width: calc(-5px + (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
left left
</div> </div>
</div> </div>
<div <div
class="divider" class="_divider_e4e78e"
data-testid="splitter-divider" data-testid="splitter-divider"
id="editor-splitter" id="editor-splitter"
> >
<div <div
class="middle" class="_middle_e4e78e"
> >
<div <div
class="buttons" class="_buttons_e4e78e"
> >
<button <button
class="btn btn-light" class="btn btn-light"
@ -220,7 +220,7 @@ exports[`Splitter resize can change size with touch 3`] = `
BootstrapIconMock_ArrowLeft BootstrapIconMock_ArrowLeft
</button> </button>
<span <span
class="grabber" class="_grabber_e4e78e"
> >
BootstrapIconMock_ArrowLeftRight BootstrapIconMock_ArrowLeftRight
</span> </span>
@ -234,12 +234,12 @@ exports[`Splitter resize can change size with touch 3`] = `
</div> </div>
</div> </div>
<div <div
class="right" class="_right_d43a0d"
id="editor-view-pane" id="editor-view-pane"
style="width: calc(100% - 50%);" style="width: calc(100% - (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
right right
</div> </div>
@ -248,32 +248,32 @@ exports[`Splitter resize can change size with touch 3`] = `
</div> </div>
`; `;
exports[`Splitter resize can change size with touch 4`] = ` exports[`Splitter > resize > can change size with touch 4`] = `
<div> <div>
<div <div
class="flex-fill flex-row d-flex " class="flex-fill flex-row d-flex "
> >
<div <div
class="left" class="_left_d43a0d"
id="editor-edit-pane" id="editor-edit-pane"
style="width: calc(50% - 5px);" style="width: calc(-5px + (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
left left
</div> </div>
</div> </div>
<div <div
class="divider" class="_divider_e4e78e"
data-testid="splitter-divider" data-testid="splitter-divider"
id="editor-splitter" id="editor-splitter"
> >
<div <div
class="middle" class="_middle_e4e78e"
> >
<div <div
class="buttons" class="_buttons_e4e78e"
> >
<button <button
class="btn btn-light" class="btn btn-light"
@ -282,7 +282,7 @@ exports[`Splitter resize can change size with touch 4`] = `
BootstrapIconMock_ArrowLeft BootstrapIconMock_ArrowLeft
</button> </button>
<span <span
class="grabber" class="_grabber_e4e78e"
> >
BootstrapIconMock_ArrowLeftRight BootstrapIconMock_ArrowLeftRight
</span> </span>
@ -296,12 +296,12 @@ exports[`Splitter resize can change size with touch 4`] = `
</div> </div>
</div> </div>
<div <div
class="right" class="_right_d43a0d"
id="editor-view-pane" id="editor-view-pane"
style="width: calc(100% - 50%);" style="width: calc(100% - (% * nan));"
> >
<div <div
class="inner" class="_inner_d43a0d"
> >
right right
</div> </div>

View file

@ -9,11 +9,13 @@ import { Mock } from 'ts-mockery'
import * as EditorConfigModule from '../../../redux/editor-config/methods' import * as EditorConfigModule from '../../../redux/editor-config/methods'
import { mockAppState } from '../../../test-utils/mock-app-state' import { mockAppState } from '../../../test-utils/mock-app-state'
import type { EditorConfig } from '../../../redux/editor-config/types' import type { EditorConfig } from '../../../redux/editor-config/types'
import { beforeEach, describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../hooks/common/use-application-state') vi.mock('../../../hooks/common/use-application-state')
jest.mock('../../../redux/editor-config/methods') vi.mock('../../../redux/editor-config/methods')
const setEditorSplitPosition = jest.spyOn(EditorConfigModule, 'setEditorSplitPosition').mockReturnValue() const setEditorSplitPosition = vitest.spyOn(EditorConfigModule, 'setEditorSplitPosition').mockReturnValue()
describe('Splitter', () => { describe('Splitter', () => {
describe('resize', () => { describe('resize', () => {

View file

@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Table of contents renders correctly 1`] = ` exports[`Table of contents > renders correctly 1`] = `
<div> <div>
<div <div
class="toc customClassName" class="_toc_e84bed customClassName"
> >
<ul> <ul>
<li> <li>
@ -39,10 +39,10 @@ exports[`Table of contents renders correctly 1`] = `
</div> </div>
`; `;
exports[`Table of contents renders only in requested max depth 1`] = ` exports[`Table of contents > renders only in requested max depth 1`] = `
<div> <div>
<div <div
class="toc customClassName" class="_toc_e84bed customClassName"
> >
<ul> <ul>
<li> <li>

View file

@ -7,6 +7,7 @@ import { mockI18n } from '../../../test-utils/mock-i18n'
import { TableOfContents } from './table-of-contents' import { TableOfContents } from './table-of-contents'
import type { TocAst } from '@hedgedoc/markdown-it-plugins' import type { TocAst } from '@hedgedoc/markdown-it-plugins'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Table of contents', () => { describe('Table of contents', () => {
beforeAll(async () => { beforeAll(async () => {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`motd modal doesn't render a modal if no motd has been fetched 1`] = ` exports[`motd modal > doesn't render a modal if no motd has been fetched 1`] = `
<div> <div>
<span <span
data-testid="loaded not visible" data-testid="loaded not visible"
@ -8,7 +8,7 @@ exports[`motd modal doesn't render a modal if no motd has been fetched 1`] = `
</div> </div>
`; `;
exports[`motd modal renders a modal if a motd was fetched and can dismiss it 1`] = ` exports[`motd modal > renders a modal if a motd was fetched and can dismiss it 1`] = `
<div> <div>
<span> <span>
This is a mock implementation of a Modal: This is a mock implementation of a Modal:
@ -39,7 +39,7 @@ exports[`motd modal renders a modal if a motd was fetched and can dismiss it 1`]
</div> </div>
`; `;
exports[`motd modal renders a modal if a motd was fetched and can dismiss it 2`] = ` exports[`motd modal > renders a modal if a motd was fetched and can dismiss it 2`] = `
<div> <div>
<span> <span>
This is a mock implementation of a Modal: This is a mock implementation of a Modal:

View file

@ -5,6 +5,7 @@
*/ */
import { fetchMotd } from './fetch-motd' import { fetchMotd } from './fetch-motd'
import { Mock } from 'ts-mockery' import { Mock } from 'ts-mockery'
import { afterEach, beforeEach, describe, expect, it, vitest, beforeAll } from 'vitest'
describe('fetch motd', () => { describe('fetch motd', () => {
const baseUrl = 'https://example.org/' const baseUrl = 'https://example.org/'
@ -14,19 +15,19 @@ describe('fetch motd', () => {
window.localStorage.clear() window.localStorage.clear()
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
beforeAll(() => { beforeAll(() => {
global.fetch = jest.fn() global.fetch = vitest.fn()
}) })
const mockFetch = ( const mockFetch = (
responseText: string, responseText: string,
lastModified: string | null, lastModified: string | null,
etag?: string | null etag?: string | null
): jest.SpyInstance<Promise<Response>> => { ): vitest.SpyInstance<Promise<Response>> => {
return jest.spyOn(global, 'fetch').mockImplementation((url: RequestInfo | URL) => { return vitest.spyOn(global, 'fetch').mockImplementation((url: RequestInfo | URL) => {
if (url !== motdUrl) { if (url !== motdUrl) {
return Promise.reject(new Error('wrong url')) return Promise.reject(new Error('wrong url'))
} }
@ -45,7 +46,7 @@ describe('fetch motd', () => {
} }
const mockFileNotFoundFetch = () => { const mockFileNotFoundFetch = () => {
jest.spyOn(global, 'fetch').mockImplementation(() => vitest.spyOn(global, 'fetch').mockImplementation(() =>
Promise.resolve( Promise.resolve(
Mock.of<Response>({ Mock.of<Response>({
status: 404 status: 404

View file

@ -14,31 +14,33 @@ import type { PropsWithChildren } from 'react'
import React from 'react' import React from 'react'
import { CachedMotdModal } from './cached-motd-modal' import { CachedMotdModal } from './cached-motd-modal'
import { MotdProvider } from '../../motd/motd-context' import { MotdProvider } from '../../motd/motd-context'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../common/modals/common-modal') vi.mock('../../common/modals/common-modal')
jest.mock('../../common/renderer-iframe/renderer-iframe') vi.mock('../../common/renderer-iframe/renderer-iframe')
jest.mock('../../../hooks/common/use-base-url') vi.mock('../../../hooks/common/use-base-url')
describe('motd modal', () => { describe('motd modal', () => {
beforeAll(async () => { beforeAll(async () => {
jest.spyOn(UseBaseUrlModule, 'useBaseUrl').mockImplementation(() => 'https://example.org') vitest.spyOn(UseBaseUrlModule, 'useBaseUrl').mockImplementation(() => 'https://example.org')
await mockI18n() await mockI18n()
}) })
afterAll(() => { afterAll(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
beforeAll(() => { beforeAll(() => {
jest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children, show }) => { vitest.spyOn(CommonModalModule, 'CommonModal').mockImplementation((({ children, show }) => {
return ( return (
<span> <span>
This is a mock implementation of a Modal: {show ? <dialog>{children}</dialog> : 'Modal is invisible'} This is a mock implementation of a Modal: {show ? <dialog>{children}</dialog> : 'Modal is invisible'}
</span> </span>
) )
}) as React.FC<PropsWithChildren<CommonModalProps>>) }) as React.FC<PropsWithChildren<CommonModalProps>>)
jest.spyOn(RendererIframeModule, 'RendererIframe').mockImplementation((props) => { vitest.spyOn(RendererIframeModule, 'RendererIframe').mockImplementation((props) => {
return ( return (
<span {...testId('motd-renderer')}> <span {...testId('motd-renderer')}>
This is a mock implementation of a iframe renderer. Props: {JSON.stringify(props)} This is a mock implementation of a iframe renderer. Props: {JSON.stringify(props)}

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`EditorSettingsTabContent hides space settings indentWithTabs is true 1`] = ` exports[`EditorSettingsTabContent > hides space settings indentWithTabs is true 1`] = `
<div> <div>
<div <div
class="list-group" class="list-group"
@ -279,7 +279,7 @@ exports[`EditorSettingsTabContent hides space settings indentWithTabs is true 1`
</div> </div>
`; `;
exports[`EditorSettingsTabContent renders space settings when indentWithTabs is false 1`] = ` exports[`EditorSettingsTabContent > renders space settings when indentWithTabs is false 1`] = `
<div> <div>
<div <div
class="list-group" class="list-group"

View file

@ -8,8 +8,10 @@ import { mockAppState } from '../../../../test-utils/mock-app-state'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { EditorSettingsTabContent } from './editor-settings-tab-content' import { EditorSettingsTabContent } from './editor-settings-tab-content'
import { mockI18n } from '../../../../test-utils/mock-i18n' import { mockI18n } from '../../../../test-utils/mock-i18n'
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
import { vi } from 'vitest'
jest.mock('../../../../hooks/common/use-application-state') vi.mock('../../../../hooks/common/use-application-state')
describe('EditorSettingsTabContent', () => { describe('EditorSettingsTabContent', () => {
beforeEach(async () => { beforeEach(async () => {
@ -17,8 +19,8 @@ describe('EditorSettingsTabContent', () => {
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() vitest.resetAllMocks()
jest.resetModules() vitest.resetModules()
}) })
it('renders space settings when indentWithTabs is false', () => { it('renders space settings when indentWithTabs is false', () => {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`language picker renders all languages 1`] = ` exports[`language picker > renders all languages 1`] = `
<div> <div>
<select <select
as="select" as="select"

View file

@ -7,9 +7,11 @@ import { mockI18n } from '../../../../test-utils/mock-i18n'
import { LanguagePicker } from './language-picker' import { LanguagePicker } from './language-picker'
import { fireEvent, render, screen } from '@testing-library/react' import { fireEvent, render, screen } from '@testing-library/react'
import i18n from 'i18next' import i18n from 'i18next'
import { describe, expect, it, vitest, beforeAll, afterAll } from 'vitest'
import { vi } from 'vitest'
jest.mock('./available-languages', () => ({ vi.mock('./available-languages', () => ({
availableLanguages: jest.fn(() => ['de', 'en']) availableLanguages: vitest.fn(() => ['de', 'en'])
})) }))
describe('language picker', () => { describe('language picker', () => {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Settings On-Off Button Group accepts custom labels 1`] = ` exports[`Settings On-Off Button Group > accepts custom labels 1`] = `
<div> <div>
<div <div
class="btn-group" class="btn-group"
@ -28,7 +28,7 @@ exports[`Settings On-Off Button Group accepts custom labels 1`] = `
</div> </div>
`; `;
exports[`Settings On-Off Button Group can switch value 1`] = ` exports[`Settings On-Off Button Group > can switch value 1`] = `
<div> <div>
<div <div
class="btn-group" class="btn-group"
@ -56,7 +56,7 @@ exports[`Settings On-Off Button Group can switch value 1`] = `
</div> </div>
`; `;
exports[`Settings On-Off Button Group can switch value 2`] = ` exports[`Settings On-Off Button Group > can switch value 2`] = `
<div> <div>
<div <div
class="btn-group" class="btn-group"

View file

@ -6,6 +6,7 @@
import { mockI18n } from '../../../../test-utils/mock-i18n' import { mockI18n } from '../../../../test-utils/mock-i18n'
import { OnOffButtonGroup } from './on-off-button-group' import { OnOffButtonGroup } from './on-off-button-group'
import { act, render, screen } from '@testing-library/react' import { act, render, screen } from '@testing-library/react'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Settings On-Off Button Group', () => { describe('Settings On-Off Button Group', () => {
beforeAll(mockI18n) beforeAll(mockI18n)

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { parseCodeBlockParameters } from './code-block-parameters' import { parseCodeBlockParameters } from './code-block-parameters'
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
describe('Code block parameter parsing', () => { describe('Code block parameter parsing', () => {
it('should detect just the language', () => { it('should detect just the language', () => {

Some files were not shown because too many files have changed in this diff Show more