Skip to content

Commit

Permalink
test: add missing tests for React hooks (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianoventura authored Sep 27, 2024
1 parent f454324 commit 3e05015
Show file tree
Hide file tree
Showing 16 changed files with 721 additions and 48 deletions.
56 changes: 56 additions & 0 deletions src/hooks/useAutoScroll.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { renderHook } from '@testing-library/react'
import React, { useRef } from 'react'
import { useAutoScroll } from './useAutoScroll'
import { describe, expect, it, vi, afterAll } from 'vitest'

vi.mock('react', async () => {
const actual = await vi.importActual<typeof React>('react')
return {
...actual,
useRef: vi.fn(),
}
})

describe('useAutoScroll', () => {
afterAll(() => {
vi.clearAllMocks()
})

it('should call scrollIntoView when items change and enabled is true', () => {
const scrollIntoViewMock = vi.fn()
const bottomRef = { current: { scrollIntoView: scrollIntoViewMock } }
vi.mocked(useRef).mockImplementation(() => bottomRef)

const { rerender } = renderHook(
({ items }: { items: number[] }) => useAutoScroll(items, true),
{
initialProps: { items: [] as number[] },
}
)

rerender({ items: [1] })

expect(scrollIntoViewMock).toHaveBeenCalledWith({
behavior: 'smooth',
block: 'end',
})
})

it('should not call scrollIntoView when enabled is false', () => {
const scrollIntoViewMock = vi.fn()
const bottomRef = { current: { scrollIntoView: scrollIntoViewMock } }
vi.mocked(useRef).mockImplementation(() => bottomRef)

const { rerender } = renderHook(
({ items, enabled }: { items: number[]; enabled: boolean }) =>
useAutoScroll(items, enabled),
{
initialProps: { items: [] as number[], enabled: false },
}
)

rerender({ items: [1], enabled: false })

expect(scrollIntoViewMock).not.toHaveBeenCalled()
})
})
25 changes: 25 additions & 0 deletions src/hooks/useCloseSplashScreen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { renderHook } from '@testing-library/react'
import { useCloseSplashScreen } from './useCloseSplashScreen'
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'

const closeSplashscreen = vi.fn()

beforeAll(() => {
vi.stubGlobal('studio', {
app: {
closeSplashscreen,
},
})
})

describe('useCloseSplashScreen', () => {
beforeEach(() => {
vi.clearAllMocks()
})

it('should call closeSplashscreen on mount', () => {
renderHook(() => useCloseSplashScreen())

expect(closeSplashscreen).toHaveBeenCalled()
})
})
91 changes: 91 additions & 0 deletions src/hooks/useCreateGenerator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { useNavigate } from 'react-router-dom'
import { useCreateGenerator } from './useCreateGenerator'
import { createNewGeneratorFile } from '@/utils/generator'
import { generateFileNameWithTimestamp } from '@/utils/file'
import { getRoutePath } from '@/routeMap'
import { useToast } from '@/store/ui/useToast'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { renderHook } from '@testing-library/react'
import { act } from 'react'
import { createGeneratorData } from '@/test/factories/generator'

vi.mock('react-router-dom', () => ({
useNavigate: vi.fn(),
}))
vi.mock('@/utils/generator', () => ({
createNewGeneratorFile: vi.fn(),
}))
vi.mock('@/utils/file', () => ({
generateFileNameWithTimestamp: vi.fn(),
}))
vi.mock('@/routeMap', () => ({
getRoutePath: vi.fn(),
}))
vi.mock('@/store/ui/useToast', () => ({
useToast: vi.fn(),
}))

describe('useCreateGenerator', () => {
const navigate = vi.fn()
const showToast = vi.fn()

beforeEach(() => {
vi.mocked(useNavigate).mockReturnValue(navigate)
vi.mocked(useToast).mockReturnValue(showToast)
vi.clearAllMocks()
})

it('should navigate to the correct path on successful generator creation', async () => {
const newGenerator = createGeneratorData()
const fileName = 'test-file.json'
const routePath = '/generator/test-file.json'

vi.mocked(createNewGeneratorFile).mockReturnValue(newGenerator)
vi.mocked(generateFileNameWithTimestamp).mockReturnValue(fileName)
vi.mocked(getRoutePath).mockReturnValue(routePath)
vi.stubGlobal('studio', {
generator: {
saveGenerator: vi.fn().mockResolvedValue(fileName),
loadGenerator: vi.fn(),
},
})

const { result } = renderHook(() => useCreateGenerator())

await act(async () => {
await result.current()
})

expect(createNewGeneratorFile).toHaveBeenCalled()
expect(generateFileNameWithTimestamp).toHaveBeenCalledWith(
'json',
'Generator'
)
expect(window.studio.generator.saveGenerator).toHaveBeenCalledWith(
JSON.stringify(newGenerator, null, 2),
fileName
)
expect(navigate).toHaveBeenCalledWith(routePath)
})

it('should show a toast message on failure', async () => {
const error = new Error('Test error')
vi.stubGlobal('studio', {
generator: {
saveGenerator: vi.fn().mockRejectedValue(error),
loadGenerator: vi.fn(),
},
})

const { result } = renderHook(() => useCreateGenerator())

await act(async () => {
await result.current()
})

expect(showToast).toHaveBeenCalledWith({
status: 'error',
title: 'Failed to create generator',
})
})
})
62 changes: 14 additions & 48 deletions src/hooks/useListenProxyData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { describe, expect, it, vi, beforeAll, afterAll } from 'vitest'
import { renderHook, act } from '@testing-library/react'
import { useListenProxyData } from './useListenProxyData'
import { ProxyData } from '@/types'
import {
createProxyData,
createProxyDataWithoutResponse,
createResponse,
} from '@/test/factories/proxyData'

type Callback = (data: ProxyData) => void

Expand Down Expand Up @@ -106,52 +111,13 @@ describe('useListenProxyData', () => {
})
})

const request: ProxyData['request'] = {
const proxyDataWithResponse = createProxyData()
const proxyDataWithoutResponse = createProxyDataWithoutResponse()
const responseWith304StatusCode = createResponse({
statusCode: 304,
content: '',
headers: [],
cookies: [],
query: [],
scheme: 'http',
host: 'example.com',
method: 'GET',
path: '/api/v1/users',
content: null,
timestampStart: 0,
timestampEnd: 0,
contentLength: 0,
httpVersion: '1.1',
url: 'http://example.com',
}

const response: ProxyData['response'] = {
statusCode: 200,
headers: [['content-type', 'application/json']],
cookies: [],
reason: 'OK',
content: '{"hello":"world"}',
path: '/api/v1/users',
httpVersion: '1.1',
timestampStart: 0,
contentLength: 0,
}

const proxyDataWithoutResponse: ProxyData = {
id: '1',
request,
}

const proxyDataWithResponse: ProxyData = {
id: '1',
request,
response,
}

const proxyDataWith304Response: ProxyData = {
...proxyDataWithResponse,
request,
response: {
...response,
statusCode: 304,
content: '',
headers: [],
},
}
})
const proxyDataWith304Response = createProxyData({
response: responseWith304StatusCode,
})
50 changes: 50 additions & 0 deletions src/hooks/useOverflowCheck.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { renderHook } from '@testing-library/react'
import { useOverflowCheck } from './useOverflowCheck'
import { beforeEach, describe, expect, it, vi } from 'vitest'

class ResizeObserverMock {
observe = vi.fn()
unobserve = vi.fn()
disconnect = vi.fn()
}

function setValueOnRef(
ref: React.RefObject<HTMLElement>,
key: string,
value: number
) {
Object.defineProperty(ref.current, key, { value, configurable: true })
}

vi.stubGlobal('ResizeObserver', ResizeObserverMock)

describe('useOverflowCheck', () => {
let ref: React.RefObject<HTMLElement>

beforeEach(() => {
ref = {
current: {
scrollWidth: 0,
clientWidth: 0,
} as HTMLElement,
}
})

it('should return true when element has overflow', () => {
setValueOnRef(ref, 'scrollWidth', 200)
setValueOnRef(ref, 'clientWidth', 100)

const { result } = renderHook(() => useOverflowCheck(ref))

expect(result.current).toBe(true)
})

it('should return false when element does not have overflow', () => {
setValueOnRef(ref, 'scrollWidth', 100)
setValueOnRef(ref, 'clientWidth', 200)

const { result } = renderHook(() => useOverflowCheck(ref))

expect(result.current).toBe(false)
})
})
44 changes: 44 additions & 0 deletions src/hooks/useProxyDataGroups.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createProxyData } from '@/test/factories/proxyData'
import { useProxyDataGroups } from './useProxyDataGroups'
import { DEFAULT_GROUP_NAME } from '@/constants'
import { ProxyData } from '@/types'
import { renderHook } from '@testing-library/react'
import { describe, it, expect } from 'vitest'

describe('useProxyDataGroups', () => {
it('should return unique group names from proxy data', () => {
const proxyData: ProxyData[] = [
createProxyData({ group: 'Group1' }),
createProxyData({ group: 'Group2' }),
createProxyData({ group: 'Group1' }),
createProxyData({ group: 'Group2' }),
createProxyData({ group: 'Group3' }),
]

const { result } = renderHook(() => useProxyDataGroups(proxyData))

expect(result.current).toEqual([
{ id: 'Group1', name: 'Group1' },
{ id: 'Group2', name: 'Group2' },
{ id: 'Group3', name: 'Group3' },
])
})

it('should handle default group names correctly', () => {
const proxyData: ProxyData[] = [createProxyData({ group: undefined })]

const { result } = renderHook(() => useProxyDataGroups(proxyData))

expect(result.current).toEqual([
{ id: DEFAULT_GROUP_NAME, name: DEFAULT_GROUP_NAME },
])
})

it('should return an empty array when no proxy data is provided', () => {
const proxyData: ProxyData[] = []

const { result } = renderHook(() => useProxyDataGroups(proxyData))

expect(result.current).toEqual([])
})
})
53 changes: 53 additions & 0 deletions src/hooks/useRunChecks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { createK6Check } from '@/test/factories/k6Check'
import { useRunChecks } from './useRunChecks'
import { K6Check } from '@/types'
import { renderHook } from '@testing-library/react'
import { act } from 'react'
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'

const onScriptCheck = vi.fn()

describe('useRunChecks', () => {
beforeAll(() => {
vi.stubGlobal('studio', {
script: {
onScriptCheck,
},
})
})

beforeEach(() => {
vi.clearAllMocks()
})

it('should initialize with an empty array of checks', () => {
const { result } = renderHook(() => useRunChecks())

expect(result.current.checks).toEqual([])
})

it('should reset checks to an empty array', () => {
const { result } = renderHook(() => useRunChecks())

act(() => {
result.current.resetChecks()
})

expect(result.current.checks).toEqual([])
})

it('should update checks when onScriptCheck is called', () => {
const mockChecks: K6Check[] = [
createK6Check({ id: '1', name: 'Check 1' }),
createK6Check({ id: '2', name: 'Check 2' }),
]
onScriptCheck.mockImplementation((callback) => {
callback(mockChecks)
return () => {}
})

const { result } = renderHook(() => useRunChecks())

expect(result.current.checks).toEqual(mockChecks)
})
})
Loading

0 comments on commit 3e05015

Please sign in to comment.