feat(kanban): requester input empty + keyboard nav (issue 0088)
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>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// 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)
|
||||
}
|
||||
Reference in New Issue
Block a user