diff --git a/README.md b/README.md index ae592e0..36090a1 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,11 @@ docker compose -f infra/docker-compose.yml up -d Set-Location backend go run ./cmd/api ``` + +## Frontend + +The web client uses Svelte and TypeScript only. The login shell lets users enter a server IP address or domain name, which is saved as the API base URL. + +## Verification + +See `docs/mvp-verification.md` for backend, web, desktop, PostgreSQL, and manual MVP verification steps. diff --git a/apps/web/e2e/project-workbench.spec.ts b/apps/web/e2e/project-workbench.spec.ts new file mode 100644 index 0000000..a1f847f --- /dev/null +++ b/apps/web/e2e/project-workbench.spec.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@playwright/test'; + +test('project workbench shell renders', async ({ page }) => { + await page.goto('/'); + await expect(page.getByText('项目工作台')).toBeVisible(); + await expect(page.getByLabel('服务器登录')).toBeVisible(); + await expect(page.getByLabel('服务器 IP 或域名')).toBeVisible(); + await expect(page.getByLabel('项目总览')).toBeVisible(); +}); diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json index 0391864..bb825b2 100644 --- a/apps/web/package-lock.json +++ b/apps/web/package-lock.json @@ -12,6 +12,7 @@ "svelte": "^5.42.0" }, "devDependencies": { + "@playwright/test": "^1.61.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/svelte": "^5.2.9", "@tsconfig/svelte": "^5.0.5", @@ -724,6 +725,22 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.62.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", @@ -2000,6 +2017,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.5.19", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.19.tgz", diff --git a/apps/web/package.json b/apps/web/package.json index 0772ab2..8a9b585 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,6 +14,7 @@ "svelte": "^5.42.0" }, "devDependencies": { + "@playwright/test": "^1.61.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/svelte": "^5.2.9", "@tsconfig/svelte": "^5.0.5", diff --git a/apps/web/playwright.config.ts b/apps/web/playwright.config.ts new file mode 100644 index 0000000..7f354be --- /dev/null +++ b/apps/web/playwright.config.ts @@ -0,0 +1,20 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + webServer: { + command: 'npm run dev -- --host 127.0.0.1', + url: 'http://127.0.0.1:5173', + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: 'http://127.0.0.1:5173', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], +}); diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts index 68be0ab..fde0ae5 100644 --- a/apps/web/src/main.ts +++ b/apps/web/src/main.ts @@ -1,5 +1,6 @@ import './index.css'; import App from './app/App.svelte'; +import { mount } from 'svelte'; const target = document.getElementById('app'); @@ -7,4 +8,4 @@ if (!target) { throw new Error('Missing #app mount target'); } -new App({ target }); +mount(App, { target }); diff --git a/apps/web/test-results/.last-run.json b/apps/web/test-results/.last-run.json new file mode 100644 index 0000000..cbcc1fb --- /dev/null +++ b/apps/web/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} \ No newline at end of file diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 86ec5f7..03d655a 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -8,6 +8,7 @@ export default defineConfig({ }, test: { environment: 'jsdom', + exclude: ['node_modules/**', 'dist/**', 'e2e/**'], globals: true, }, }); diff --git a/docs/mvp-verification.md b/docs/mvp-verification.md new file mode 100644 index 0000000..fde62fb --- /dev/null +++ b/docs/mvp-verification.md @@ -0,0 +1,64 @@ +# MVP Verification + +## Backend + +Run: + +```powershell +Set-Location backend +go test ./... -v +``` + +Expected: all backend tests pass. + +## PostgreSQL Integration + +Use this test database URL when live PostgreSQL verification is required: + +```text +postgres://postgres:Weidong2023~!@8.137.107.29:19432/agent_dev?sslmode=disable +``` + +Do not hardcode this value into application source files. Pass it through `DATABASE_URL`. + +## Web + +The frontend is Svelte-only. + +Run: + +```powershell +Set-Location apps/web +npm test -- --run +npm run build +npx playwright test +``` + +Expected: component tests, production build, and smoke test pass. + +## Desktop + +Run: + +```powershell +Set-Location apps/web +npm run build +Set-Location ../desktop +npm run build +``` + +Expected: Tauri desktop bundle builds when Rust/Cargo is installed. On this machine, verification currently fails before compilation because `cargo` is not available in PATH. + +## Manual MVP Flow + +1. Open the client and enter the server IP or domain on the login screen. +2. Create or log in as a private-deployment user. +3. Create a project. +4. Add text to project inbox. +5. Click Analyze/Organize. +6. Confirm one task and one note from the suggestion list. +7. Assign the task to another system user. +8. Explicitly share one note with the task. +9. Search for text from the note body in global search. +10. Open an AI session under the project and reference the note. +11. Use Tauri quick capture to send text into the active project inbox.