experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

headless tests, so much less annoying

+50 -21
+8
backend/electron/config.ts
··· 20 20 let _profile: string = ''; 21 21 22 22 /** 23 + * Check if running in headless mode (no visible windows) 24 + * Set PEEK_HEADLESS=1 to enable 25 + */ 26 + export function isHeadless(): boolean { 27 + return !!process.env.PEEK_HEADLESS; 28 + } 29 + 30 + /** 23 31 * Set runtime paths (called during app initialization) 24 32 */ 25 33 export function setPreloadPath(preloadPath: string): void {
+1
backend/electron/index.ts
··· 18 18 getProfile, 19 19 isTestProfile, 20 20 isDevProfile, 21 + isHeadless, 21 22 } from './config.js'; 22 23 23 24 // Database lifecycle and helpers
+5 -2
backend/electron/ipc.ts
··· 59 59 getPreloadPath, 60 60 IPC_CHANNELS, 61 61 TOPICS, 62 + isHeadless, 62 63 } from './config.js'; 63 64 64 65 import { ··· 697 698 const existingWindow = findWindowByKey(msg.source, options.key); 698 699 if (existingWindow) { 699 700 console.log('Reusing existing window with key:', options.key); 700 - existingWindow.window.show(); 701 + if (!isHeadless()) { 702 + existingWindow.window.show(); 703 + } 701 704 return { success: true, id: existingWindow.id, reused: true }; 702 705 } 703 706 } ··· 707 710 ...options, 708 711 width: parseInt(options.width) || APP_DEF_WIDTH, 709 712 height: parseInt(options.height) || APP_DEF_HEIGHT, 710 - show: options.show !== false, 713 + show: isHeadless() ? false : options.show !== false, 711 714 webPreferences: { 712 715 ...options.webPreferences, 713 716 preload: getPreloadPath()
+7 -5
backend/electron/main.ts
··· 14 14 import { initTray } from './tray.js'; 15 15 import { registerLocalShortcut, unregisterLocalShortcut, handleLocalShortcut, registerGlobalShortcut, unregisterGlobalShortcut, unregisterShortcutsForAddress } from './shortcuts.js'; 16 16 import { scopes, publish, subscribe, setExtensionBroadcaster, getSystemAddress } from './pubsub.js'; 17 - import { APP_DEF_WIDTH, APP_DEF_HEIGHT, WEB_CORE_ADDRESS, getPreloadPath, isTestProfile } from './config.js'; 17 + import { APP_DEF_WIDTH, APP_DEF_HEIGHT, WEB_CORE_ADDRESS, getPreloadPath, isTestProfile, isHeadless } from './config.js'; 18 18 import { addEscHandler, winDevtoolsConfig, closeOrHideWindow } from './windows.js'; 19 19 20 20 // Configuration ··· 378 378 const win = new BrowserWindow(winPrefs); 379 379 win.loadURL(WEB_CORE_ADDRESS); 380 380 381 - // Setup devtools for the background window (debug mode, but not in tests) 382 - if (config.isDev && !isTestProfile()) { 381 + // Setup devtools for the background window (debug mode, but not in tests or headless) 382 + if (config.isDev && !isTestProfile() && !isHeadless()) { 383 383 win.webContents.openDevTools({ mode: 'detach', activate: false }); 384 384 } 385 385 ··· 417 417 const existingWindow = findWindowByKey(WEB_CORE_ADDRESS, featuresMap.key as string); 418 418 if (existingWindow) { 419 419 console.log('Reusing existing window with key:', featuresMap.key); 420 - existingWindow.window.show(); 420 + if (!isHeadless()) { 421 + existingWindow.window.show(); 422 + } 421 423 return { action: 'deny' as const }; 422 424 } 423 425 } ··· 427 429 ...(featuresMap as Electron.BrowserWindowConstructorOptions), 428 430 width: parseInt(String(featuresMap.width)) || APP_DEF_WIDTH, 429 431 height: parseInt(String(featuresMap.height)) || APP_DEF_HEIGHT, 430 - show: featuresMap.show !== false, 432 + show: isHeadless() ? false : featuresMap.show !== false, 431 433 webPreferences: { 432 434 preload: preloadPath 433 435 }
+3 -2
backend/electron/windows.ts
··· 9 9 WEB_CORE_ADDRESS, 10 10 SETTINGS_ADDRESS, 11 11 isTestProfile, 12 + isHeadless, 12 13 } from './config.js'; 13 14 import { 14 15 getWindowInfo, ··· 123 124 124 125 console.log('winDevtoolsConfig:', bw.id, 'openDevTools:', params.openDevTools, 'address:', params.address); 125 126 126 - // Check if devTools should be opened (never in test profiles) 127 - if (params.openDevTools === true && !isTestProfile()) { 127 + // Check if devTools should be opened (never in test profiles or headless mode) 128 + if (params.openDevTools === true && !isTestProfile() && !isHeadless()) { 128 129 const isDetached = params.detachedDevTools === true; 129 130 // Determine if detached mode should be used 130 131 // activate: false prevents devtools from stealing focus (only works with detach/undocked)
+2
package.json
··· 33 33 "make": "electron-builder", 34 34 "lint": "echo \"No linting configured\"", 35 35 "help": "electron --help", 36 + "smoke": "./scripts/smoke-test.sh", 37 + "smoke:visible": "./scripts/smoke-test.sh --visible", 36 38 "test": "npx playwright test", 37 39 "test:smoke": "npx playwright test tests/smoke.spec.ts", 38 40 "test:headed": "npx playwright test --headed",
scripts/kill-dev.sh
+24 -12
scripts/smoke-test.sh
··· 1 1 #!/bin/bash 2 2 # Smoke test script - runs the app briefly to verify it starts correctly 3 - # Usage: ./scripts/smoke-test.sh [duration_seconds] [extra_args...] 4 - # Example: ./scripts/smoke-test.sh 10 5 - # Example: ./scripts/smoke-test.sh 15 --some-flag 3 + # Usage: ./scripts/smoke-test.sh [--visible] [duration_seconds] 4 + # Example: ./scripts/smoke-test.sh # headless, 10s 5 + # Example: ./scripts/smoke-test.sh 15 # headless, 15s 6 + # Example: ./scripts/smoke-test.sh --visible # visible windows, 10s 7 + # Example: ./scripts/smoke-test.sh --visible 15 8 + 9 + HEADLESS=1 10 + if [ "$1" = "--visible" ]; then 11 + HEADLESS=0 12 + shift 13 + fi 6 14 7 15 DURATION=${1:-10} 8 - shift 2>/dev/null || true 9 16 10 17 # Generate unique profile name for this test run 11 18 PROFILE="test-smoke-$$" ··· 15 22 cleanup() { 16 23 if [ -f "$PIDFILE" ]; then 17 24 PID=$(cat "$PIDFILE") 18 - kill "$PID" 2>/dev/null 25 + # Kill the process group to get all children 26 + kill -TERM -"$PID" 2>/dev/null || kill -TERM "$PID" 2>/dev/null || true 27 + sleep 0.5 28 + kill -9 -"$PID" 2>/dev/null || kill -9 "$PID" 2>/dev/null || true 19 29 rm -f "$PIDFILE" 20 30 fi 21 - # Also kill any remaining electron processes with our test profile 22 - pkill -f "PROFILE=$PROFILE" 2>/dev/null || true 23 - pkill -f "$PROFILE" 2>/dev/null || true 31 + # Kill any remaining electron processes from this project 32 + pkill -9 -f "/Users/dietrich/misc/peek/node_modules/electron" 2>/dev/null || true 24 33 } 25 34 26 35 trap cleanup EXIT 27 36 28 - echo "Starting smoke test (profile: $PROFILE, duration: ${DURATION}s)..." 29 - 30 - # Start the app in background 31 - PROFILE="$PROFILE" DEBUG=1 yarn start "$@" > "$LOGFILE" 2>&1 & 37 + if [ "$HEADLESS" = "1" ]; then 38 + echo "Starting smoke test (profile: $PROFILE, duration: ${DURATION}s, headless)..." 39 + PROFILE="$PROFILE" DEBUG=1 PEEK_HEADLESS=1 yarn start > "$LOGFILE" 2>&1 & 40 + else 41 + echo "Starting smoke test (profile: $PROFILE, duration: ${DURATION}s, visible)..." 42 + PROFILE="$PROFILE" DEBUG=1 yarn start > "$LOGFILE" 2>&1 & 43 + fi 32 44 echo $! > "$PIDFILE" 33 45 34 46 # Wait for specified duration