diff --git a/electron/tests/e2e/thread.e2e.spec.ts b/electron/tests/e2e/thread.e2e.spec.ts index c13e91119..5d7328053 100644 --- a/electron/tests/e2e/thread.e2e.spec.ts +++ b/electron/tests/e2e/thread.e2e.spec.ts @@ -1,32 +1,29 @@ import { expect } from '@playwright/test' import { page, test, TIMEOUT } from '../config/fixtures' -test('Select GPT model from Hub and Chat with Invalid API Key', async ({ hubPage }) => { +test('Select GPT model from Hub and Chat with Invalid API Key', async ({ + hubPage, +}) => { await hubPage.navigateByMenu() await hubPage.verifyContainerVisible() // Select the first GPT model await page .locator('[data-testid^="use-model-btn"][data-testid*="gpt"]') - .first().click() - - // Attempt to create thread and chat in Thread page - await page - .getByTestId('btn-create-thread') + .first() .click() - await page - .getByTestId('txt-input-chat') - .fill('dummy value') + await page.getByTestId('txt-input-chat').fill('dummy value') - await page - .getByTestId('btn-send-chat') - .click() + await page.getByTestId('btn-send-chat').click() - await page.waitForFunction(() => { - const loaders = document.querySelectorAll('[data-testid$="loader"]'); - return !loaders.length; - }, { timeout: TIMEOUT }); + await page.waitForFunction( + () => { + const loaders = document.querySelectorAll('[data-testid$="loader"]') + return !loaders.length + }, + { timeout: TIMEOUT } + ) const APIKeyError = page.getByTestId('invalid-API-key-error') await expect(APIKeyError).toBeVisible({ diff --git a/web/containers/Layout/RibbonPanel/index.tsx b/web/containers/Layout/RibbonPanel/index.tsx index 6bed2b424..7613584e0 100644 --- a/web/containers/Layout/RibbonPanel/index.tsx +++ b/web/containers/Layout/RibbonPanel/index.tsx @@ -12,17 +12,18 @@ import { twMerge } from 'tailwind-merge' import { MainViewState } from '@/constants/screens' -import { localEngines } from '@/utils/modelEngine' - import { mainViewStateAtom, showLeftPanelAtom } from '@/helpers/atoms/App.atom' import { editMessageAtom } from '@/helpers/atoms/ChatMessage.atom' import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' -import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom' + import { reduceTransparentAtom, selectedSettingAtom, } from '@/helpers/atoms/Setting.atom' -import { threadsAtom } from '@/helpers/atoms/Thread.atom' +import { + isDownloadALocalModelAtom, + threadsAtom, +} from '@/helpers/atoms/Thread.atom' export default function RibbonPanel() { const [mainViewState, setMainViewState] = useAtom(mainViewStateAtom) @@ -32,8 +33,9 @@ export default function RibbonPanel() { const matches = useMediaQuery('(max-width: 880px)') const reduceTransparent = useAtomValue(reduceTransparentAtom) const setSelectedSetting = useSetAtom(selectedSettingAtom) - const downloadedModels = useAtomValue(downloadedModelsAtom) + const threads = useAtomValue(threadsAtom) + const isDownloadALocalModel = useAtomValue(isDownloadALocalModelAtom) const onMenuClick = (state: MainViewState) => { if (mainViewState === state) return @@ -43,10 +45,6 @@ export default function RibbonPanel() { setEditMessage('') } - const isDownloadALocalModel = downloadedModels.some((x) => - localEngines.includes(x.engine) - ) - const RibbonNavMenus = [ { name: 'Thread', diff --git a/web/containers/Layout/TopPanel/index.tsx b/web/containers/Layout/TopPanel/index.tsx index 213f7dfa9..aff616973 100644 --- a/web/containers/Layout/TopPanel/index.tsx +++ b/web/containers/Layout/TopPanel/index.tsx @@ -23,6 +23,7 @@ import { toaster } from '@/containers/Toast' import { MainViewState } from '@/constants/screens' import { useCreateNewThread } from '@/hooks/useCreateNewThread' +import { useStarterScreen } from '@/hooks/useStarterScreen' import { mainViewStateAtom, @@ -58,6 +59,8 @@ const TopPanel = () => { requestCreateNewThread(assistants[0]) } + const { isShowStarterScreen } = useStarterScreen() + return (
{ )} )} - {mainViewState === MainViewState.Thread && ( + {mainViewState === MainViewState.Thread && !isShowStarterScreen && ( - + {toGibibytes(featModel.metadata.size)}
@@ -257,7 +271,7 @@ const OnDeviceStarterScreen = ({ extensionHasSettings }: Props) => { ) })} -
+

Cloud Models

@@ -268,7 +282,7 @@ const OnDeviceStarterScreen = ({ extensionHasSettings }: Props) => { return (
{row.map((remoteEngine) => { const engineLogo = getLogoEngine( @@ -298,7 +312,7 @@ const OnDeviceStarterScreen = ({ extensionHasSettings }: Props) => { /> )} -

+

{getTitleByEngine( remoteEngine as InferenceEngine )} diff --git a/web/screens/Thread/index.test.tsx b/web/screens/Thread/index.test.tsx new file mode 100644 index 000000000..01af0ffc5 --- /dev/null +++ b/web/screens/Thread/index.test.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import { render, screen } from '@testing-library/react' +import ThreadScreen from './index' +import { useStarterScreen } from '../../hooks/useStarterScreen' +import '@testing-library/jest-dom' + +global.ResizeObserver = class { + observe() {} + unobserve() {} + disconnect() {} +} +// Mock the useStarterScreen hook +jest.mock('@/hooks/useStarterScreen') + +describe('ThreadScreen', () => { + it('renders OnDeviceStarterScreen when isShowStarterScreen is true', () => { + ;(useStarterScreen as jest.Mock).mockReturnValue({ + isShowStarterScreen: true, + extensionHasSettings: false, + }) + + const { getByText } = render() + expect(getByText('Select a model to start')).toBeInTheDocument() + }) + + it('renders Thread panels when isShowStarterScreen is false', () => { + ;(useStarterScreen as jest.Mock).mockReturnValue({ + isShowStarterScreen: false, + extensionHasSettings: false, + }) + + const { getByText } = render() + expect(getByText('Welcome!')).toBeInTheDocument() + }) +})