* chore: enhance onboarding screen's models * chore: lint fix * chore: correct lint fix command * chore: fix tests
201 lines
5.1 KiB
TypeScript
201 lines
5.1 KiB
TypeScript
import React from 'react'
|
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
import { Provider } from 'jotai'
|
|
import OnDeviceStarterScreen from './index'
|
|
import * as jotai from 'jotai'
|
|
import '@testing-library/jest-dom'
|
|
|
|
jest.mock('jotai', () => ({
|
|
...jest.requireActual('jotai'),
|
|
useAtomValue: jest.fn(),
|
|
useSetAtom: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('next/image', () => ({
|
|
__esModule: true,
|
|
default: (props: any) => <img {...props} />,
|
|
}))
|
|
|
|
jest.mock('@janhq/joi', () => ({
|
|
Button: (props: any) => <button {...props} />,
|
|
Input: ({ prefixIcon, ...props }: any) => (
|
|
<div>
|
|
{prefixIcon}
|
|
<input {...props} />
|
|
</div>
|
|
),
|
|
Progress: () => <div data-testid="progress" />,
|
|
ScrollArea: ({ children }: any) => <div>{children}</div>,
|
|
useClickOutside: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/containers/Brand/Logo/Mark', () => () => (
|
|
<div data-testid="logo-mark" />
|
|
))
|
|
jest.mock('@/containers/CenterPanelContainer', () => ({ children }: any) => (
|
|
<div>{children}</div>
|
|
))
|
|
jest.mock('@/containers/Loader/ProgressCircle', () => () => (
|
|
<div data-testid="progress-circle" />
|
|
))
|
|
jest.mock('@/containers/ModelLabel', () => () => (
|
|
<div data-testid="model-label" />
|
|
))
|
|
|
|
jest.mock('@/hooks/useDownloadModel', () => ({
|
|
__esModule: true,
|
|
default: () => ({ downloadModel: jest.fn() }),
|
|
}))
|
|
|
|
// Mock the necessary atoms
|
|
const mockAtomValue = jest.spyOn(jotai, 'useAtomValue')
|
|
const mockSetAtom = jest.spyOn(jotai, 'useSetAtom')
|
|
|
|
jest.mock('@/hooks/useModelSource')
|
|
|
|
import * as source from '@/hooks/useModelSource'
|
|
|
|
describe('OnDeviceStarterScreen', () => {
|
|
beforeEach(() => {
|
|
mockAtomValue.mockImplementation(() => [])
|
|
mockSetAtom.mockImplementation(() => jest.fn())
|
|
})
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: [],
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
|
|
it('renders the component', () => {
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: [],
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
render(
|
|
<Provider>
|
|
<OnDeviceStarterScreen isShowStarterScreen={true} />
|
|
</Provider>
|
|
)
|
|
|
|
expect(screen.getByText('Select a model to start')).toBeInTheDocument()
|
|
expect(screen.getByTestId('logo-mark')).toBeInTheDocument()
|
|
})
|
|
|
|
it('handles search input', () => {
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: [],
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
render(
|
|
<Provider>
|
|
<OnDeviceStarterScreen isShowStarterScreen={true} />
|
|
</Provider>
|
|
)
|
|
|
|
const searchInput = screen.getByPlaceholderText('Search...')
|
|
fireEvent.change(searchInput, { target: { value: 'test model' } })
|
|
|
|
expect(searchInput).toHaveValue('test model')
|
|
})
|
|
|
|
it('displays "No Result Found" when no models match the search', () => {
|
|
mockAtomValue.mockImplementation(() => [])
|
|
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: [],
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
render(
|
|
<Provider>
|
|
<OnDeviceStarterScreen isShowStarterScreen={true} />
|
|
</Provider>
|
|
)
|
|
|
|
const searchInput = screen.getByPlaceholderText('Search...')
|
|
fireEvent.change(searchInput, { target: { value: 'nonexistent model' } })
|
|
|
|
expect(screen.getByText('No Result Found')).toBeInTheDocument()
|
|
})
|
|
|
|
it('renders featured models', () => {
|
|
const mockConfiguredModels = [
|
|
{
|
|
id: 'cortexso/deepseek-r1',
|
|
name: 'DeepSeek R1',
|
|
metadata: {
|
|
tags: ['Featured'],
|
|
author: 'Test Author',
|
|
size: 3000000000,
|
|
},
|
|
models: [
|
|
{
|
|
id: 'cortexso/deepseek-r1',
|
|
name: 'DeepSeek R1',
|
|
metadata: {
|
|
tags: ['Featured'],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'cortexso/llama3.2',
|
|
name: 'Llama 3.1',
|
|
metadata: { tags: [], author: 'Test Author', size: 2000000000 },
|
|
models: [
|
|
{
|
|
id: 'cortexso/deepseek-r1',
|
|
name: 'DeepSeek R1',
|
|
metadata: {
|
|
tags: ['Featured'],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: mockConfiguredModels,
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
|
|
render(
|
|
<Provider>
|
|
<OnDeviceStarterScreen isShowStarterScreen={true} />
|
|
</Provider>
|
|
)
|
|
|
|
expect(screen.getAllByText('deepseek-r1')[0]).toBeInTheDocument()
|
|
})
|
|
|
|
it('renders cloud models', () => {
|
|
jest.spyOn(source, 'useGetModelSources').mockReturnValue({
|
|
sources: [],
|
|
error: null,
|
|
mutate: jest.fn(),
|
|
})
|
|
const mockRemoteModels = [
|
|
{ id: 'remote-model-1', name: 'Remote Model 1', engine: 'openai' },
|
|
{ id: 'remote-model-2', name: 'Remote Model 2', engine: 'anthropic' },
|
|
]
|
|
|
|
mockAtomValue.mockImplementation((atom) => {
|
|
if (atom === jotai.atom([])) {
|
|
return mockRemoteModels
|
|
}
|
|
return []
|
|
})
|
|
|
|
render(
|
|
<Provider>
|
|
<OnDeviceStarterScreen isShowStarterScreen={true} />
|
|
</Provider>
|
|
)
|
|
|
|
expect(screen.getByText('Cloud Models')).toBeInTheDocument()
|
|
})
|
|
})
|