BREAKING CHANGE: Application now uses config.yaml instead of .env files ## Changes: - Remove dotenv dependency from package.json - Update all services to use ConfigManager for configuration - Update tests to use fixed credentials instead of env vars - Delete obsolete config-manager.test.ts (used old .env API) - Update documentation (README.md, CLAUDE.md) to reflect new config system ## Configuration Architecture: - ConfigManager: Centralized YAML configuration with Zod validation - config.yaml location: - Development: Project root (easy to edit and version control) - Production: User AppData (persists across updates) - ERP credentials: Stored in database (dbo_BIPUsers) per user - Other settings: Stored in config.yaml (database, paths, extraction, etc.) ## Files Modified: - package.json: Removed dotenv dependency - cleaner-handler.ts: Use ConfigManager.getDatabaseType() - run-migration.ts: Read from config.yaml instead of .env - All integration tests: Use fixed test credentials - tests/setup.ts: Removed dotenv loading - README.md, CLAUDE.md: Updated documentation Migration is complete. Application no longer depends on .env files.
93 lines
3.1 KiB
TypeScript
93 lines
3.1 KiB
TypeScript
/**
|
|
* E2E Tests for Authentication Flow
|
|
*
|
|
* Tests the complete authentication workflow including:
|
|
* - Silent login
|
|
* - Manual login
|
|
* - Logout
|
|
* - Session management
|
|
*/
|
|
|
|
import { test, expect, ElectronApplication, Page } from '@playwright/test'
|
|
import { _electron as electron } from 'playwright'
|
|
import path from 'path'
|
|
|
|
let electronApp: ElectronApplication
|
|
let page: Page
|
|
|
|
test.describe('Authentication Flow', () => {
|
|
test.beforeAll(async () => {
|
|
// Launch Electron app
|
|
electronApp = await electron.launch({
|
|
args: [path.join(__dirname, '../../out/main/index.js')],
|
|
env: {
|
|
NODE_ENV: 'test'
|
|
}
|
|
})
|
|
|
|
// Get the first window
|
|
page = await electronApp.firstWindow()
|
|
|
|
// Wait for app to load
|
|
await page.waitForLoadState('domcontentloaded')
|
|
})
|
|
|
|
test.afterAll(async () => {
|
|
await electronApp.close()
|
|
})
|
|
|
|
test('should show login dialog on first load', async () => {
|
|
// Check if login dialog or main content is visible
|
|
const loginDialog = page.locator('[data-testid="login-dialog"]')
|
|
const mainContent = page.locator('[data-testid="main-content"]')
|
|
|
|
// Either login dialog or main content should be visible
|
|
const isLoginVisible = await loginDialog.isVisible().catch(() => false)
|
|
const isMainVisible = await mainContent.isVisible().catch(() => false)
|
|
|
|
expect(isLoginVisible || isMainVisible).toBe(true)
|
|
})
|
|
|
|
test('should have login form elements', async () => {
|
|
// Check for login form elements if login dialog is visible
|
|
const usernameInput = page.locator('input[type="text"], input[name="username"]')
|
|
const passwordInput = page.locator('input[type="password"], input[name="password"]')
|
|
const loginButton = page.locator('button:has-text("登录"), button:has-text("Login")')
|
|
|
|
// Check if at least one of each exists
|
|
const hasUsername = await usernameInput.count()
|
|
const hasPassword = await passwordInput.count()
|
|
const hasLoginButton = await loginButton.count()
|
|
|
|
// If login dialog is shown, these elements should exist
|
|
if (hasUsername > 0 || hasPassword > 0) {
|
|
expect(hasUsername).toBeGreaterThan(0)
|
|
expect(hasPassword).toBeGreaterThan(0)
|
|
expect(hasLoginButton).toBeGreaterThan(0)
|
|
}
|
|
})
|
|
|
|
test('should show error on invalid credentials', async () => {
|
|
const usernameInput = page.locator('input[type="text"], input[name="username"]').first()
|
|
const passwordInput = page.locator('input[type="password"], input[name="password"]').first()
|
|
const loginButton = page.locator('button:has-text("登录"), button:has-text("Login")').first()
|
|
|
|
// Only test if login form is visible
|
|
if (await usernameInput.isVisible().catch(() => false)) {
|
|
await usernameInput.fill('invalid_user')
|
|
await passwordInput.fill('invalid_password')
|
|
await loginButton.click()
|
|
|
|
// Wait for error message
|
|
await page.waitForTimeout(1000)
|
|
|
|
// Check for error message
|
|
const errorMessage = page.locator('.error, [role="alert"], .text-red')
|
|
const hasError = await errorMessage.count()
|
|
|
|
// Either error shown or still on login page
|
|
expect(hasError >= 0).toBe(true)
|
|
}
|
|
})
|
|
})
|