eb1c13d82c
CardForm: drop pre-fill of requester from logged user; Enter inside the Autocomplete no longer submits the form (Mantine handles dropdown selection; arrows + Enter pick option without closing modal). Submit remains via "Crear" button or Ctrl+Enter from description. Adds data-field="requester" and data-test="add-card" selectors for stable e2e queries. Tests: - vitest component test (CardForm.test.tsx): empty input, Enter does not submit, submit only via button. Dropdown arrow nav covered by e2e (jsdom portal handling is brittle). - Playwright e2e (requester-input.spec.ts) using new browser capability group (pw_kanban_login, pw_keyboard_sequence) from registry. - seed_e2e_user CLI to create deterministic test user against operations.db (bcrypt via standard backend hash). Setup additions (frontend/): - vitest + @testing-library + jsdom devDeps - @playwright/test devDep + playwright.config.ts - src/test/setup.ts polyfills jsdom for Mantine (matchMedia, visualViewport, document.fonts, ResizeObserver) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
// seed_e2e_user creates or updates a deterministic test user for Playwright e2e.
|
|
// Usage: go run ./backend/cmd/seed_e2e_user --db apps/kanban/operations.db
|
|
//
|
|
// Idempotent: safe to run repeatedly. The user "e2e_user" / password "e2e_test_pw_2026"
|
|
// is intentional and used by apps/kanban/frontend/e2e/*.spec.ts when env vars are not set.
|
|
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
func main() {
|
|
dbPath := flag.String("db", "operations.db", "path to kanban operations.db")
|
|
username := flag.String("username", "e2e_user", "username")
|
|
password := flag.String("password", "e2e_test_pw_2026", "password")
|
|
displayName := flag.String("display", "E2E Test", "display name")
|
|
flag.Parse()
|
|
|
|
db, err := sql.Open("sqlite3", *dbPath)
|
|
if err != nil {
|
|
fail(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(*password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
fail(err)
|
|
}
|
|
|
|
now := time.Now().UTC().Format(time.RFC3339Nano)
|
|
id := "e2etest" + fmt.Sprintf("%x", time.Now().UnixNano())[:9]
|
|
|
|
// Try update first
|
|
res, err := db.Exec(
|
|
`UPDATE users SET password_hash=?, display_name=? WHERE username=?`,
|
|
string(hash), *displayName, *username,
|
|
)
|
|
if err != nil {
|
|
fail(err)
|
|
}
|
|
n, _ := res.RowsAffected()
|
|
if n > 0 {
|
|
fmt.Printf("updated existing user %q\n", *username)
|
|
return
|
|
}
|
|
|
|
_, err = db.Exec(
|
|
`INSERT INTO users (id, username, password_hash, display_name, created_at) VALUES (?, ?, ?, ?, ?)`,
|
|
id, *username, string(hash), *displayName, now,
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
fail(err)
|
|
}
|
|
fail(err)
|
|
}
|
|
fmt.Printf("created user %q (id=%s)\n", *username, id)
|
|
}
|
|
|
|
func fail(err error) {
|
|
fmt.Fprintln(os.Stderr, "seed_e2e_user:", err)
|
|
os.Exit(1)
|
|
}
|