feat: add Playwright e2e smoke test covering signup → household → chore flow

- Added smoke.spec.js with Playwright test for full user flow:
  1. Sign up (fill form, submit, click 'Go to Dashboard')
  2. Create household (fill name, submit)
  3. Create chore (fill name + date, submit)
  4. Verify session persistence (revisit dashboard)
- Server now supports --db flag for temp databases and SIS_FRESH_DB env
  to delete the db file on startup (for clean test runs)
- Server reads SIS_PORT env var for port configuration
- scripts/test-e2e: starts server with fresh db, runs tests, cleans up
- playwright.config.js: minimal config pointing at test/e2e/
This commit is contained in:
2026-07-16 10:01:33 -04:00
parent 6bea83be7d
commit 1c19d97dc8
6 changed files with 214 additions and 3 deletions
+23 -3
View File
@@ -1,10 +1,12 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-unused-imports -Wno-missing-export-lists -Wno-name-shadowing #-}
module Main where
import Control.Exception (IOException, catch)
import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as C8
import Data.ByteString.Lazy qualified as BL
@@ -13,8 +15,10 @@ import Effectful
import Network.HTTP.Types qualified as HTTP
import Network.Wai qualified as Wai
import Network.Wai.Handler.Warp qualified as Warp
import System.Directory (createDirectoryIfMissing, doesFileExist)
import System.Directory (createDirectoryIfMissing, doesFileExist, removeFile)
import System.Environment (getArgs, lookupEnv)
import System.FilePath (takeDirectory)
import System.IO.Error (isDoesNotExistError)
import Sis.Database
import Sis.Page.Activity
@@ -43,13 +47,29 @@ mimeType fp
main :: IO ()
main = do
let dbPath = "data/sis.db"
args <- getArgs
let dbPath = case args of
("--db" : p : _) -> p
_ -> "data/sis.db"
-- Use PORT env var or --port arg or default 8080
mPortEnv <- lookupEnv "PORT"
mPortArg <- lookupEnv "SIS_PORT"
let port = case (mPortEnv, mPortArg, args) of
(Just p, _, _) -> read p
(_, Just p, _) -> read p
(_, _, "--port" : p : _) -> read p
_ -> 8080
-- For fresh test databases, remove the file so tables are recreated
rmDB <- lookupEnv "SIS_FRESH_DB"
case rmDB of
Just _ -> removeFile dbPath `catch` (\(_ :: IOException) -> pure ())
Nothing -> pure ()
createDirectoryIfMissing True (takeDirectory dbPath)
putStrLn "[sis] opening database..."
conn <- openDatabase dbPath
let port = 8080
putStrLn $ "[sis] listening on 0.0.0.0:" <> show port
let hyperboleApp =