* fix: #1142 - Toggle off experimental toggle does not turn off gated features * test: add tests
This commit is contained in:
parent
8e603bd5db
commit
031b3517dc
@ -100,6 +100,7 @@ const DataFolder = () => {
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div className="relative">
|
||||
<Input
|
||||
data-testid="jan-data-folder-input"
|
||||
value={janDataFolderPath}
|
||||
className="w-full pr-8 sm:w-[240px]"
|
||||
disabled
|
||||
|
||||
@ -22,7 +22,11 @@ const FactoryReset = () => {
|
||||
recommended only if the application is in a corrupted state.
|
||||
</p>
|
||||
</div>
|
||||
<Button theme="destructive" onClick={() => setModalValidation(true)}>
|
||||
<Button
|
||||
data-testid="reset-button"
|
||||
theme="destructive"
|
||||
onClick={() => setModalValidation(true)}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
<ModalValidation />
|
||||
|
||||
154
web/screens/Settings/Advanced/index.test.tsx
Normal file
154
web/screens/Settings/Advanced/index.test.tsx
Normal file
@ -0,0 +1,154 @@
|
||||
import React from 'react'
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
||||
import '@testing-library/jest-dom'
|
||||
import Advanced from '.'
|
||||
|
||||
class ResizeObserverMock {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
}
|
||||
|
||||
global.ResizeObserver = ResizeObserverMock
|
||||
// @ts-ignore
|
||||
global.window.core = {
|
||||
api: {
|
||||
getAppConfigurations: () => jest.fn(),
|
||||
updateAppConfiguration: () => jest.fn(),
|
||||
relaunch: () => jest.fn(),
|
||||
},
|
||||
}
|
||||
|
||||
const setSettingsMock = jest.fn()
|
||||
|
||||
// Mock useSettings hook
|
||||
jest.mock('@/hooks/useSettings', () => ({
|
||||
__esModule: true,
|
||||
useSettings: () => ({
|
||||
readSettings: () => ({
|
||||
run_mode: 'gpu',
|
||||
experimental: false,
|
||||
proxy: false,
|
||||
gpus: [{ name: 'gpu-1' }, { name: 'gpu-2' }],
|
||||
gpus_in_use: ['0'],
|
||||
quick_ask: false,
|
||||
}),
|
||||
setSettings: setSettingsMock,
|
||||
}),
|
||||
}))
|
||||
|
||||
import * as toast from '@/containers/Toast'
|
||||
|
||||
jest.mock('@/containers/Toast')
|
||||
|
||||
jest.mock('@janhq/core', () => ({
|
||||
__esModule: true,
|
||||
...jest.requireActual('@janhq/core'),
|
||||
fs: {
|
||||
rm: jest.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
// Simulate a full advanced settings screen
|
||||
// @ts-ignore
|
||||
global.isMac = false
|
||||
// @ts-ignore
|
||||
global.isWindows = true
|
||||
|
||||
describe('Advanced', () => {
|
||||
it('renders the component', async () => {
|
||||
render(<Advanced />)
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Experimental Mode')).toBeInTheDocument()
|
||||
expect(screen.getByText('HTTPS Proxy')).toBeInTheDocument()
|
||||
expect(screen.getByText('Ignore SSL certificates')).toBeInTheDocument()
|
||||
expect(screen.getByText('Jan Data Folder')).toBeInTheDocument()
|
||||
expect(screen.getByText('Reset to Factory Settings')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it('updates Experimental enabled', async () => {
|
||||
render(<Advanced />)
|
||||
let experimentalToggle
|
||||
await waitFor(() => {
|
||||
experimentalToggle = screen.getByTestId(/experimental-switch/i)
|
||||
fireEvent.click(experimentalToggle!)
|
||||
})
|
||||
expect(experimentalToggle).toBeChecked()
|
||||
})
|
||||
|
||||
it('updates Experimental disabled', async () => {
|
||||
render(<Advanced />)
|
||||
|
||||
let experimentalToggle
|
||||
await waitFor(() => {
|
||||
experimentalToggle = screen.getByTestId(/experimental-switch/i)
|
||||
fireEvent.click(experimentalToggle!)
|
||||
})
|
||||
expect(experimentalToggle).not.toBeChecked()
|
||||
})
|
||||
|
||||
it('clears logs', async () => {
|
||||
const jestMock = jest.fn()
|
||||
jest.spyOn(toast, 'toaster').mockImplementation(jestMock)
|
||||
|
||||
render(<Advanced />)
|
||||
let clearLogsButton
|
||||
await waitFor(() => {
|
||||
clearLogsButton = screen.getByTestId(/clear-logs/i)
|
||||
fireEvent.click(clearLogsButton)
|
||||
})
|
||||
expect(clearLogsButton).toBeInTheDocument()
|
||||
expect(jestMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('toggles proxy enabled', async () => {
|
||||
render(<Advanced />)
|
||||
let proxyToggle
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('HTTPS Proxy')).toBeInTheDocument()
|
||||
proxyToggle = screen.getByTestId(/proxy-switch/i)
|
||||
fireEvent.click(proxyToggle)
|
||||
})
|
||||
expect(proxyToggle).toBeChecked()
|
||||
})
|
||||
|
||||
it('updates proxy settings', async () => {
|
||||
render(<Advanced />)
|
||||
let proxyInput
|
||||
await waitFor(() => {
|
||||
const proxyToggle = screen.getByTestId(/proxy-switch/i)
|
||||
fireEvent.click(proxyToggle)
|
||||
proxyInput = screen.getByTestId(/proxy-input/i)
|
||||
fireEvent.change(proxyInput, { target: { value: 'http://proxy.com' } })
|
||||
})
|
||||
expect(proxyInput).toHaveValue('http://proxy.com')
|
||||
})
|
||||
|
||||
it('toggles ignore SSL certificates', async () => {
|
||||
render(<Advanced />)
|
||||
let ignoreSslToggle
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Ignore SSL certificates')).toBeInTheDocument()
|
||||
ignoreSslToggle = screen.getByTestId(/ignore-ssl-switch/i)
|
||||
fireEvent.click(ignoreSslToggle)
|
||||
})
|
||||
expect(ignoreSslToggle).toBeChecked()
|
||||
})
|
||||
|
||||
it('renders DataFolder component', async () => {
|
||||
render(<Advanced />)
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Jan Data Folder')).toBeInTheDocument()
|
||||
expect(screen.getByTestId(/jan-data-folder-input/i)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it('renders FactoryReset component', async () => {
|
||||
render(<Advanced />)
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Reset to Factory Settings')).toBeInTheDocument()
|
||||
expect(screen.getByTestId(/reset-button/i)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -43,19 +43,10 @@ type GPU = {
|
||||
name: string
|
||||
}
|
||||
|
||||
const test = [
|
||||
{
|
||||
id: 'test a',
|
||||
vram: 2,
|
||||
name: 'nvidia A',
|
||||
},
|
||||
{
|
||||
id: 'test',
|
||||
vram: 2,
|
||||
name: 'nvidia B',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* Advanced Settings Screen
|
||||
* @returns
|
||||
*/
|
||||
const Advanced = () => {
|
||||
const [experimentalEnabled, setExperimentalEnabled] = useAtom(
|
||||
experimentalFeatureEnabledAtom
|
||||
@ -69,7 +60,7 @@ const Advanced = () => {
|
||||
|
||||
const [partialProxy, setPartialProxy] = useState<string>(proxy)
|
||||
const [gpuEnabled, setGpuEnabled] = useState<boolean>(false)
|
||||
const [gpuList, setGpuList] = useState<GPU[]>(test)
|
||||
const [gpuList, setGpuList] = useState<GPU[]>([])
|
||||
const [gpusInUse, setGpusInUse] = useState<string[]>([])
|
||||
const [dropdownOptions, setDropdownOptions] = useState<HTMLDivElement | null>(
|
||||
null
|
||||
@ -87,6 +78,9 @@ const Advanced = () => {
|
||||
return y['name']
|
||||
})
|
||||
|
||||
/**
|
||||
* Handle proxy change
|
||||
*/
|
||||
const onProxyChange = useCallback(
|
||||
(event: ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.value || ''
|
||||
@ -100,6 +94,12 @@ const Advanced = () => {
|
||||
[setPartialProxy, setProxy]
|
||||
)
|
||||
|
||||
/**
|
||||
* Update Quick Ask Enabled
|
||||
* @param e
|
||||
* @param relaunch
|
||||
* @returns void
|
||||
*/
|
||||
const updateQuickAskEnabled = async (
|
||||
e: boolean,
|
||||
relaunch: boolean = true
|
||||
@ -111,6 +111,12 @@ const Advanced = () => {
|
||||
if (relaunch) window.core?.api?.relaunch()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Vulkan Enabled
|
||||
* @param e
|
||||
* @param relaunch
|
||||
* @returns void
|
||||
*/
|
||||
const updateVulkanEnabled = async (e: boolean, relaunch: boolean = true) => {
|
||||
toaster({
|
||||
title: 'Reload',
|
||||
@ -123,11 +129,19 @@ const Advanced = () => {
|
||||
if (relaunch) window.location.reload()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Experimental Enabled
|
||||
* @param e
|
||||
* @returns
|
||||
*/
|
||||
const updateExperimentalEnabled = async (
|
||||
e: ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
setExperimentalEnabled(e.target.checked)
|
||||
if (e) return
|
||||
|
||||
// If it checked, we don't need to do anything else
|
||||
// Otherwise have to reset other settings
|
||||
if (e.target.checked) return
|
||||
|
||||
// It affects other settings, so we need to reset them
|
||||
const isRelaunch = quickAskEnabled || vulkanEnabled
|
||||
@ -136,6 +150,9 @@ const Advanced = () => {
|
||||
if (isRelaunch) window.core?.api?.relaunch()
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect to set GPU enabled if possible
|
||||
*/
|
||||
useEffect(() => {
|
||||
const setUseGpuIfPossible = async () => {
|
||||
const settings = await readSettings()
|
||||
@ -149,6 +166,10 @@ const Advanced = () => {
|
||||
setUseGpuIfPossible()
|
||||
}, [readSettings, setGpuList, setGpuEnabled, setGpusInUse, setVulkanEnabled])
|
||||
|
||||
/**
|
||||
* Clear logs
|
||||
* @returns
|
||||
*/
|
||||
const clearLogs = async () => {
|
||||
try {
|
||||
await fs.rm(`file://logs`)
|
||||
@ -163,6 +184,11 @@ const Advanced = () => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GPU Change
|
||||
* @param gpuId
|
||||
* @returns
|
||||
*/
|
||||
const handleGPUChange = (gpuId: string) => {
|
||||
let updatedGpusInUse = [...gpusInUse]
|
||||
if (updatedGpusInUse.includes(gpuId)) {
|
||||
@ -188,6 +214,9 @@ const Advanced = () => {
|
||||
const gpuSelectionPlaceHolder =
|
||||
gpuList.length > 0 ? 'Select GPU' : "You don't have any compatible GPU"
|
||||
|
||||
/**
|
||||
* Handle click outside
|
||||
*/
|
||||
useClickOutside(() => setOpen(false), null, [dropdownOptions, toggle])
|
||||
|
||||
return (
|
||||
@ -204,6 +233,7 @@ const Advanced = () => {
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
data-testid="experimental-switch"
|
||||
checked={experimentalEnabled}
|
||||
onChange={updateExperimentalEnabled}
|
||||
/>
|
||||
@ -401,11 +431,13 @@ const Advanced = () => {
|
||||
|
||||
<div className="flex w-full flex-shrink-0 flex-col items-end gap-2 pr-1 sm:w-1/2">
|
||||
<Switch
|
||||
data-testid="proxy-switch"
|
||||
checked={proxyEnabled}
|
||||
onChange={() => setProxyEnabled(!proxyEnabled)}
|
||||
/>
|
||||
<div className="w-full">
|
||||
<Input
|
||||
data-testid="proxy-input"
|
||||
placeholder={'http://<user>:<password>@<domain or IP>:<port>'}
|
||||
value={partialProxy}
|
||||
onChange={onProxyChange}
|
||||
@ -428,6 +460,7 @@ const Advanced = () => {
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
data-testid="ignore-ssl-switch"
|
||||
checked={ignoreSSL}
|
||||
onChange={(e) => setIgnoreSSL(e.target.checked)}
|
||||
/>
|
||||
@ -448,6 +481,7 @@ const Advanced = () => {
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
data-testid="quick-ask-switch"
|
||||
checked={quickAskEnabled}
|
||||
onChange={() => {
|
||||
toaster({
|
||||
@ -471,7 +505,11 @@ const Advanced = () => {
|
||||
Clear all logs from Jan app.
|
||||
</p>
|
||||
</div>
|
||||
<Button theme="destructive" onClick={clearLogs}>
|
||||
<Button
|
||||
data-testid="clear-logs"
|
||||
theme="destructive"
|
||||
onClick={clearLogs}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user