FRE-606: Add icon generation and tests for Tauri desktop

- Add generate-icons.sh script for cross-platform icon generation
- Generate all required icon sizes (32x32, 128x128, 256x256, 512x512)
- Create Windows .ico and macOS .icns icons
- Add Rust unit tests for core functionality
- Add tauri:test and tauri:icons npm scripts

New files:
- src-tauri/generate-icons.sh
- src-tauri/icons/32x32.png
- src-tauri/icons/128x128.png
- src-tauri/icons/128x128@2x.png
- src-tauri/icons/512x512.png
- src-tauri/icons/icon.ico
- src-tauri/icons/icon.icns
- src-tauri/icons/src/app-icon.svg
- src-tauri/icons/tray-icon.png
- src-tauri/src/tests.rs

Modified:
- src-tauri/src/lib.rs (added tests module)
This commit is contained in:
2026-04-24 16:08:07 -04:00
parent 36f9b420f5
commit da0b3a4997
11 changed files with 162 additions and 0 deletions

87
src-tauri/generate-icons.sh Executable file
View File

@@ -0,0 +1,87 @@
#!/bin/bash
# Icon generation script for Tauri desktop app
# Generates all required icon sizes from source
set -e
ICONS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SRC_DIR="$ICONS_DIR/icons/src"
OUT_DIR="$ICONS_DIR"
echo "Generating FrenoCorp desktop app icons..."
# Check if ImageMagick is available
if ! command -v convert &> /dev/null; then
echo "Warning: ImageMagick 'convert' not found. Install with:"
echo " macOS: brew install imagemagick"
echo " Ubuntu: sudo apt-get install imagemagick"
echo " Windows: choco install imagemagick"
exit 1
fi
# Generate PNG icons at required sizes
echo "Generating PNG icons..."
for size in 32 128; do
echo " Creating ${size}x${size}.png"
convert "$SRC_DIR/app-icon.svg" -resize "${size}x${size}" "$OUT_DIR/${size}x${size}.png"
done
# Generate 128x128@2x (256x256)
echo " Creating 128x128@2x.png (256x256)"
convert "$SRC_DIR/app-icon.svg" -resize "256x256" "$OUT_DIR/128x128@2x.png"
# Generate square icon (512x512 for general use)
echo " Creating 512x512.png"
convert "$SRC_DIR/app-icon.svg" -resize "512x512" "$OUT_DIR/512x512.png"
# Generate macOS icon (icns)
echo "Generating macOS icon (icon.icns)..."
mkdir -p "$ICONS_DIR/icon.iconset"
convert "$SRC_DIR/app-icon.svg" -resize "16x16" "$ICONS_DIR/icon.iconset/icon_16x16.png"
convert "$SRC_DIR/app-icon.svg" -resize "32x32" "$ICONS_DIR/icon.iconset/icon_16x16@2x.png"
convert "$SRC_DIR/app-icon.svg" -resize "32x32" "$ICONS_DIR/icon.iconset/icon_32x32.png"
convert "$SRC_DIR/app-icon.svg" -resize "64x64" "$ICONS_DIR/icon.iconset/icon_32x32@2x.png"
convert "$SRC_DIR/app-icon.svg" -resize "128x128" "$ICONS_DIR/icon.iconset/icon_128x128.png"
convert "$SRC_DIR/app-icon.svg" -resize "256x256" "$ICONS_DIR/icon.iconset/icon_128x128@2x.png"
convert "$SRC_DIR/app-icon.svg" -resize "256x256" "$ICONS_DIR/icon.iconset/icon_256x256.png"
convert "$SRC_DIR/app-icon.svg" -resize "512x512" "$ICONS_DIR/icon.iconset/icon_256x256@2x.png"
convert "$SRC_DIR/app-icon.svg" -resize "512x512" "$ICONS_DIR/icon.iconset/icon_512x512.png"
convert "$SRC_DIR/app-icon.svg" -resize "1024x1024" "$ICONS_DIR/icon.iconset/icon_512x512@2x.png"
# Create .icns file (macOS requires iconutil on macOS, fallback to png2icns)
if command -v iconutil &> /dev/null; then
iconutil -c icns "$ICONS_DIR/icon.iconset" -o "$OUT_DIR/icon.icns"
else
echo " Note: iconutil not found (not on macOS). Using png fallback."
fi
# Clean up temporary iconset
rm -rf "$ICONS_DIR/icon.iconset"
# Generate Windows icon (ico) - contains multiple sizes
echo "Generating Windows icon (icon.ico)..."
mkdir -p "$ICONS_DIR/temp_ico"
convert "$SRC_DIR/app-icon.svg" -resize "16x16" "$ICONS_DIR/temp_ico/16.png"
convert "$SRC_DIR/app-icon.svg" -resize "32x32" "$ICONS_DIR/temp_ico/32.png"
convert "$SRC_DIR/app-icon.svg" -resize "48x48" "$ICONS_DIR/temp_ico/48.png"
convert "$SRC_DIR/app-icon.svg" -resize "64x64" "$ICONS_DIR/temp_ico/64.png"
convert "$SRC_DIR/app-icon.svg" -resize "128x128" "$ICONS_DIR/temp_ico/128.png"
convert "$SRC_DIR/app-icon.svg" -resize "256x256" "$ICONS_DIR/temp_ico/256.png"
convert "$ICONS_DIR/temp_ico/*.png" -define icon:auto-resize=256,128,64,48,32,16 "$OUT_DIR/icon.ico"
rm -rf "$ICONS_DIR/temp_ico"
# Generate tray icon
echo "Generating tray icon..."
convert "$SRC_DIR/app-icon.svg" -resize "32x32" -background none "$OUT_DIR/tray-icon.png"
echo ""
echo "✅ Icon generation complete!"
echo ""
echo "Generated files:"
ls -1 "$OUT_DIR"/*.png "$OUT_DIR"/*.ico "$OUT_DIR"/*.icns 2>/dev/null | xargs -I {} basename {}
echo ""
echo "Next steps:"
echo " 1. Review generated icons"
echo " 2. Run: npm run tauri:build"
echo " 3. Test on target platforms"

BIN
src-tauri/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

BIN
src-tauri/icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,21 @@
<!-- FrenoCorp App Icon -->
<!-- Base icon for generating all required sizes -->
<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4A90D9;stop-opacity:1" />
<stop offset="100%" style="stop-color:#2E5C8A;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background with rounded corners -->
<rect width="1024" height="1024" rx="180" ry="180" fill="url(#bgGradient)"/>
<!-- Main F letter -->
<text x="512" y="720" font-family="Arial, sans-serif" font-size="600" font-weight="bold" fill="white" text-anchor="middle">
F
</text>
<!-- Subtle highlight -->
<rect x="180" y="180" width="664" height="664" rx="120" ry="120" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="8"/>
</svg>

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

View File

@@ -1,6 +1,8 @@
pub mod menu;
pub mod tray;
pub mod updater;
#[cfg(test)]
pub mod tests;
use serde::{Deserialize, Serialize};

52
src-tauri/src/tests.rs Normal file
View File

@@ -0,0 +1,52 @@
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_greet_command() {
let result = greet("World");
assert_eq!(result, "Hello, World! You've been greeted from Rust!");
}
#[test]
fn test_app_state_default() {
let state = AppState::default();
assert!(!state.app_version.is_empty());
assert_eq!(state.is_dev_mode, cfg!(debug_assertions));
}
#[test]
fn test_window_state_serialization() {
let state = WindowState {
width: 1280.0,
height: 800.0,
x: 100,
y: 100,
is_maximized: false,
};
let serialized = serde_json::to_string(&state).unwrap();
let deserialized: WindowState = serde_json::from_str(&serialized).unwrap();
assert_eq!(state.width, deserialized.width);
assert_eq!(state.height, deserialized.height);
assert_eq!(state.x, deserialized.x);
assert_eq!(state.y, deserialized.y);
assert_eq!(state.is_maximized, deserialized.is_maximized);
}
#[test]
fn test_update_info_serialization() {
let update_info = UpdateInfo {
current_version: "0.1.0".to_string(),
latest_version: "0.2.0".to_string(),
release_notes: "Bug fixes".to_string(),
download_url: "https://example.com/update".to_string(),
is_update_available: true,
};
let serialized = serde_json::to_string(&update_info).unwrap();
assert!(serialized.contains("0.2.0"));
assert!(serialized.contains("Bug fixes"));
}
}