Skip to content

Commit

Permalink
test: add tests to model settings's Slider Input (janhq#3615)
Browse files Browse the repository at this point in the history
* test: add tests to model settings's Slider Input

* test: add slider test

* test: fix expectation

* test: correct slider test
  • Loading branch information
louis-jan authored Sep 10, 2024
1 parent ac67247 commit 2d05134
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ electron/test-data
electron/test-results
core/test_results.html
coverage
.yarn
.yarnrc
2 changes: 1 addition & 1 deletion electron/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ module.exports = {
{ name: 'Link', linkAttribute: 'to' },
],
},
ignorePatterns: ['build', 'renderer', 'node_modules', '@global'],
ignorePatterns: ['build', 'renderer', 'node_modules', '@global', 'playwright-report'],
}
1 change: 1 addition & 0 deletions web/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
'**/*.test.tsx',
'**/*.test.ts',
'testRunner.js',
'jest.config.js',
],
extends: [
'next/core-web-vitals',
Expand Down
92 changes: 92 additions & 0 deletions web/containers/SliderRightPanel/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react'
import { render } from '@testing-library/react'
import { fireEvent } from '@testing-library/dom'
import SliderRightPanel from './index'
import '@testing-library/jest-dom'

class ResizeObserverMock {
observe() {}
unobserve() {}
disconnect() {}
}

global.ResizeObserver = ResizeObserverMock

jest.mock('@janhq/joi', () => ({
...jest.requireActual('@janhq/joi'),
Slider: ({ children, onValueChange, ...props }: any) => (
<div data-testid="slider-root" {...props}>
<input
data-testid="slider-input"
type="number"
{...props}
onChange={(e: any) =>
onValueChange && onValueChange([parseInt(e.target.value)])
}
/>
{children}
</div>
),
}))

describe('SliderRightPanel', () => {
const defaultProps = {
title: 'Test Slider',
disabled: false,
min: 0,
max: 100,
step: 1,
description: 'This is a test slider',
value: 50,
onValueChanged: jest.fn(),
}

it('renders correctly with given props', () => {
const { getByText } = render(<SliderRightPanel {...defaultProps} />)
expect(getByText('Test Slider')).toBeInTheDocument()
})

it('calls onValueChanged with correct value when input is changed', () => {
defaultProps.onValueChanged = jest.fn()
const { getByRole } = render(<SliderRightPanel {...defaultProps} />)

const input = getByRole('textbox')
fireEvent.change(input, { target: { value: '75' } })
expect(defaultProps.onValueChanged).toHaveBeenCalledWith(75)
})

it('calls onValueChanged with correct value when slider is changed', () => {
defaultProps.onValueChanged = jest.fn()
const { getByTestId } = render(<SliderRightPanel {...defaultProps} />)

const input = getByTestId('slider-input')
fireEvent.change(input, { target: { value: '75' } })
expect(defaultProps.onValueChanged).toHaveBeenCalledWith(75)
})

it('calls onValueChanged with max value when input exceeds max', () => {
defaultProps.onValueChanged = jest.fn()
const { getByRole } = render(<SliderRightPanel {...defaultProps} />)
const input = getByRole('textbox')
fireEvent.change(input, { target: { value: '150' } })
fireEvent.focusOut(input)
expect(defaultProps.onValueChanged).toHaveBeenCalledWith(100)
})

it('calls onValueChanged with min value when input is below min', () => {
defaultProps.onValueChanged = jest.fn()
const { getByRole } = render(<SliderRightPanel {...defaultProps} />)
const input = getByRole('textbox')
fireEvent.change(input, { target: { value: '0' } })
fireEvent.focusOut(input)
expect(defaultProps.onValueChanged).toHaveBeenCalledWith(0)
})

it('does not call onValueChanged when input is invalid', () => {
defaultProps.onValueChanged = jest.fn()
const { getByRole } = render(<SliderRightPanel {...defaultProps} />)
const input = getByRole('textbox')
fireEvent.change(input, { target: { value: 'invalid' } })
expect(defaultProps.onValueChanged).not.toHaveBeenCalledWith(0)
})
})
12 changes: 11 additions & 1 deletion web/containers/SliderRightPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useClickOutside } from '@janhq/joi'
import { InfoIcon } from 'lucide-react'

type Props = {
name: string
name?: string
title: string
disabled: boolean
description: string
Expand Down Expand Up @@ -87,7 +87,17 @@ const SliderRightPanel = ({
}
}}
onChange={(e) => {
// Should not accept invalid value or NaN
// E.g. anything changes that trigger onValueChanged
// Which is incorrect
if (Number(e.target.value) > Number(max)) {
setVal(max.toString())
} else if (Number(e.target.value) < Number(min)) {
setVal(min.toString())
} else if (Number.isNaN(Number(e.target.value))) return

onValueChanged?.(Number(e.target.value))
// TODO: How to support negative number input?
if (/^\d*\.?\d*$/.test(e.target.value)) {
setVal(e.target.value)
}
Expand Down
5 changes: 2 additions & 3 deletions web/hooks/useCreateNewThread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,8 @@ export const useCreateNewThread = () => {
tools: experimentalEnabled ? [assistantTools] : assistant.tools,
model: {
id: defaultModel?.id ?? '*',
settings: { ...defaultModel?.settings, ...overriddenSettings } ?? {},
parameters:
{ ...defaultModel?.parameters, ...overriddenParameters } ?? {},
settings: { ...defaultModel?.settings, ...overriddenSettings },
parameters: { ...defaultModel?.parameters, ...overriddenParameters },
engine: defaultModel?.engine,
},
instructions,
Expand Down
18 changes: 14 additions & 4 deletions web/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
runner: './testRunner.js',
const nextJest = require('next/jest')

/** @type {import('jest').Config} */
const createJestConfig = nextJest({})

// Add any custom config to be passed to Jest
const config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(config)
2 changes: 2 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
},
"devDependencies": {
"@next/eslint-plugin-next": "^14.0.1",
"@testing-library/react": "^16.0.1",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.200",
"@types/node": "20.8.10",
Expand All @@ -74,6 +75,7 @@
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"jest-environment-jsdom": "^29.7.0",
"jest-runner": "^29.7.0",
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.6",
Expand Down
5 changes: 3 additions & 2 deletions web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"typeRoots": [
"./node_modules/@types",
"./src/types",
"../node_modules/@types/jest"
"../node_modules/@types/jest",
"@testing-library/jest-dom"
],
"allowJs": true,
"skipLibCheck": true,
Expand All @@ -29,5 +30,5 @@
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules", "**/*.test.ts"]
"exclude": ["node_modules"]
}

0 comments on commit 2d05134

Please sign in to comment.