From 5b95668945245a918a519c356a20c3c24a2c57cd Mon Sep 17 00:00:00 2001 From: yanweidong Date: Sun, 19 Jul 2026 19:01:27 +0800 Subject: [PATCH] feat: add full workbench login page --- apps/web/src/app/App.svelte | 79 +++---------------- apps/web/src/features/auth/ServerLogin.svelte | 63 +++++++++++---- .../web/src/features/auth/ServerLogin.test.ts | 49 ++++++++++++ 3 files changed, 110 insertions(+), 81 deletions(-) create mode 100644 apps/web/src/features/auth/ServerLogin.test.ts diff --git a/apps/web/src/app/App.svelte b/apps/web/src/app/App.svelte index a4c6389..a5d8dce 100644 --- a/apps/web/src/app/App.svelte +++ b/apps/web/src/app/App.svelte @@ -1,76 +1,21 @@ -
- - -
- -
-

AI 整理建议

- -

已选择 {selectedSuggestionCount} 项

-
-
-
+{#if currentUser} +
+

SenlinAI Workbench

+

Signed in as {currentUser.account}

+
+{:else} + +{/if} diff --git a/apps/web/src/features/auth/ServerLogin.svelte b/apps/web/src/features/auth/ServerLogin.svelte index 8e80261..8e16cb9 100644 --- a/apps/web/src/features/auth/ServerLogin.svelte +++ b/apps/web/src/features/auth/ServerLogin.svelte @@ -1,16 +1,11 @@ - +
+ +
diff --git a/apps/web/src/features/auth/ServerLogin.test.ts b/apps/web/src/features/auth/ServerLogin.test.ts new file mode 100644 index 0000000..7298b4b --- /dev/null +++ b/apps/web/src/features/auth/ServerLogin.test.ts @@ -0,0 +1,49 @@ +import '@testing-library/jest-dom/vitest'; +import { fireEvent, render, screen } from '@testing-library/svelte'; +import { describe, expect, it, vi } from 'vitest'; +import ServerLogin from './ServerLogin.svelte'; + +describe('ServerLogin', () => { + it('renders server, account, and password fields', () => { + render(ServerLogin, { props: { apiBase: 'http://localhost:8080' } }); + + expect(screen.getByLabelText('Server IP or domain')).toBeInTheDocument(); + expect(screen.getByLabelText('Email or username')).toBeInTheDocument(); + expect(screen.getByLabelText('Password')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Log in' })).toBeInTheDocument(); + }); + + it('normalizes server address and emits login details', async () => { + const onLogin = vi.fn(); + render(ServerLogin, { + props: { + apiBase: 'localhost:8080', + onLogin, + }, + }); + + await fireEvent.input(screen.getByLabelText('Server IP or domain'), { + target: { value: '10.0.0.12:8080' }, + }); + await fireEvent.input(screen.getByLabelText('Email or username'), { + target: { value: 'david@example.com' }, + }); + await fireEvent.input(screen.getByLabelText('Password'), { + target: { value: 'secret' }, + }); + await fireEvent.click(screen.getByRole('button', { name: 'Log in' })); + + expect(onLogin).toHaveBeenCalledWith({ + apiBase: 'http://10.0.0.12:8080', + account: 'david@example.com', + }); + }); + + it('shows an error when account or password is missing', async () => { + render(ServerLogin, { props: { apiBase: 'http://localhost:8080' } }); + + await fireEvent.click(screen.getByRole('button', { name: 'Log in' })); + + expect(screen.getByText('Enter an account and password.')).toBeInTheDocument(); + }); +});