Adds basic tests.

This commit is contained in:
2025-06-28 08:17:12 -07:00
parent 2968042236
commit 0399bd54cf
13 changed files with 539 additions and 0 deletions

3
.gitignore vendored
View File

@@ -10,3 +10,6 @@ CLAUDE.md
# Wild Cloud
**/config/secrets.env
**/config/config.env
# Test directory - ignore temporary files
test/tmp

9
.gitmodules vendored Normal file
View File

@@ -0,0 +1,9 @@
[submodule "test/bats"]
path = test/bats
url = https://github.com/bats-core/bats-core.git
[submodule "test/test_helper/bats-support"]
path = test/test_helper/bats-support
url = https://github.com/bats-core/bats-support.git
[submodule "test/test_helper/bats-assert"]
path = test/test_helper/bats-assert
url = https://github.com/bats-core/bats-assert.git

104
test/README.md Normal file
View File

@@ -0,0 +1,104 @@
# Test Directory
This directory is used for testing wild-cloud functionality using the Bats testing framework.
## Contents
- `test_helper.bash` - Shared Bats test setup and utilities
- `test_helper/` - Bats framework extensions (bats-support, bats-assert)
- `bats/` - Bats core framework (git submodule)
- `fixtures/` - Test data and sample configuration files
- `*.bats` - Bats test files for different components
- `run_bats_tests.sh` - Runs the complete Bats test suite
- `tmp/` - Temporary test projects (auto-created/cleaned)
## Test Files
### `test_common_functions.bats`
Tests the core functions in `wild-common.sh`:
- `find_wc_home()` - Project root detection
- `init_wild_env()` - Environment setup
- `check_wild_directory()` - Project validation
- Print functions and utilities
### `test_project_detection.bats`
Tests project detection and script execution:
- Script execution from various directory levels
- Environment variable setup from different paths
- Proper failure outside project directories
### `test_config_functions.bats`
Tests configuration and secret access:
- `get_current_config()` function
- `get_current_secret()` function
- Configuration access from subdirectories
- Fixture data usage
## Running Tests
```bash
# Initialize git submodules (first time only)
git submodule update --init --recursive
# Run all Bats tests
./run_bats_tests.sh
# Run individual test files
./bats/bin/bats test_common_functions.bats
./bats/bin/bats test_project_detection.bats
./bats/bin/bats test_config_functions.bats
# Test from subdirectory (should work)
cd deep/nested/path
../../../bin/wild-cluster-node-up --help
```
## Fixtures
The `fixtures/` directory contains:
- `sample-config.yaml` - Complete test configuration
- `sample-secrets.yaml` - Test secrets file
## Adding New Tests
1. Create `test_<feature>.bats` following the Bats pattern:
```bash
#!/usr/bin/env bats
load 'test_helper'
setup() {
setup_test_project "feature-test"
}
teardown() {
teardown_test_project "feature-test"
}
@test "feature description" {
# Your test here using Bats assertions
run some_command
assert_success
assert_output "expected output"
}
```
2. Add test data to `fixtures/` if needed
3. The Bats runner will automatically discover and run new tests
## Common Test Functions
From `test_helper.bash`:
- `setup_test_project "name"` - Creates test project in `tmp/`
- `teardown_test_project "name"` - Removes test project
- `create_test_project "name" [with-config]` - Creates additional test projects
- `remove_test_project "name"` - Removes additional test projects
## Bats Assertions
Available through bats-assert:
- `assert_success` / `assert_failure` - Check command exit status
- `assert_output "text"` - Check exact output
- `assert_output --partial "text"` - Check output contains text
- `assert_equal "$actual" "$expected"` - Check equality
- `assert [ condition ]` - General assertions

1
test/bats Submodule

Submodule test/bats added at 855844b834

72
test/fixtures/sample-config.yaml vendored Normal file
View File

@@ -0,0 +1,72 @@
wildcloud:
root: /test/path/wild-cloud
operator:
email: test@example.com
cloud:
domain: test.example.com
internalDomain: internal.test.example.com
dockerRegistryHost: docker-registry.internal.test.example.com
tz: America/New_York
router:
dynamicDns: test.ddns.com
ip: 192.168.100.1
nfs:
host: test-nfs
mediaPath: /data/media
storageCapacity: 100Gi
dns:
ip: 192.168.100.50
externalResolver: 8.8.8.8
dhcpRange: 192.168.100.100,192.168.100.200
dnsmasq:
interface: eth0
username: testuser
cluster:
name: test-cluster
ipAddressPool: 192.168.100.240-192.168.100.249
loadBalancerIp: 192.168.100.240
kubernetes:
config: /home/testuser/.kube/config
context: default
dashboard:
adminUsername: admin
certManager:
namespace: cert-manager
cloudflare:
domain: example.com
ownerId: test-cluster-owner
externalDns:
ownerId: test-cluster-owner
dockerRegistry:
storage: 10Gi
nodes:
talos:
version: v1.10.4
schematicId: test123456789abcdef
control:
vip: 192.168.100.200
active:
192.168.100.201:
maintenanceIp: 192.168.100.131
interface: eth0
disk: /dev/sda
control: "true"
192.168.100.202:
interface: eth0
disk: /dev/nvme0n1
control: "true"
192.168.100.210:
interface: eth0
disk: /dev/sda
control: "false"
apps:
postgres:
database: postgres
user: postgres
storage: 10Gi
image: pgvector/pgvector:pg15
timezone: America/New_York
redis:
image: redis:alpine
timezone: UTC
port: 6379

14
test/fixtures/sample-secrets.yaml vendored Normal file
View File

@@ -0,0 +1,14 @@
operator:
cloudflareApiToken: test_api_token_123456789
cluster:
dashboard:
adminPassword: test_admin_password_123
certManager:
cloudflare:
apiToken: test_cf_token_456789
apps:
postgres:
password: test_postgres_password_789
databases:
immich:
password: test_immich_db_password_321

25
test/run_bats_tests.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# run_bats_tests.sh
# Run all Bats tests in the test directory
set -e
# Get the directory where this script is located
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Check if bats is available
if [ ! -f "$TEST_DIR/bats/bin/bats" ]; then
echo "Error: Bats not found. Make sure git submodules are initialized:"
echo " git submodule update --init --recursive"
exit 1
fi
echo "Running Wild Cloud Bats Test Suite..."
echo "======================================"
# Run all .bats files
"$TEST_DIR/bats/bin/bats" "$TEST_DIR"/*.bats
echo ""
echo "All tests completed!"

View File

@@ -0,0 +1,86 @@
#!/usr/bin/env bats
# test_common_functions.bats
# Tests for the wild-common.sh library functions
load 'test_helper'
setup() {
setup_test_project "common-test"
cd "$TEST_PROJECT_DIR"
}
teardown() {
teardown_test_project "common-test"
}
@test "find_wc_home from project root" {
cd "$TEST_PROJECT_DIR"
WC_HOME_RESULT=$(find_wc_home)
assert_equal "$WC_HOME_RESULT" "$TEST_PROJECT_DIR"
}
@test "find_wc_home from nested subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/deep/nested/path"
cd "$TEST_PROJECT_DIR/deep/nested/path"
WC_HOME_RESULT=$(find_wc_home)
assert_equal "$WC_HOME_RESULT" "$TEST_PROJECT_DIR"
}
@test "find_wc_home when no project found" {
cd /tmp
run find_wc_home
assert_failure
}
@test "init_wild_env sets WC_HOME correctly" {
mkdir -p "$TEST_PROJECT_DIR/deep/nested"
cd "$TEST_PROJECT_DIR/deep/nested"
unset WC_HOME WC_ROOT
init_wild_env
assert_equal "$WC_HOME" "$TEST_PROJECT_DIR"
}
@test "init_wild_env sets WC_ROOT correctly" {
cd "$TEST_PROJECT_DIR"
unset WC_HOME WC_ROOT
init_wild_env
# WC_ROOT is set (value depends on test execution context)
assert [ -n "$WC_ROOT" ]
}
@test "check_wild_directory passes when in project" {
cd "$TEST_PROJECT_DIR"
run check_wild_directory
assert_success
}
@test "print functions work correctly" {
cd "$TEST_PROJECT_DIR"
run bash -c '
source "$PROJECT_ROOT/bin/wild-common.sh"
print_header "Test Header"
print_info "Test info message"
print_warning "Test warning message"
print_success "Test success message"
print_error "Test error message"
'
assert_success
assert_output --partial "Test Header"
assert_output --partial "Test info message"
}
@test "command_exists works for existing command" {
run command_exists "bash"
assert_success
}
@test "command_exists fails for nonexistent command" {
run command_exists "nonexistent-command-xyz"
assert_failure
}
@test "generate_random_string produces correct length" {
RANDOM_STR=$(generate_random_string 16)
assert_equal "${#RANDOM_STR}" "16"
}

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bats
# test_config_functions.bats
# Tests for config and secret access functions
load 'test_helper'
setup() {
setup_test_project "config-test"
cd "$TEST_PROJECT_DIR"
init_wild_env
}
teardown() {
teardown_test_project "config-test"
}
@test "get_current_config with existing config" {
CLUSTER_NAME=$(get_current_config "cluster.name")
assert_equal "$CLUSTER_NAME" "test-cluster"
}
@test "get_current_config with nested path" {
VIP=$(get_current_config "cluster.nodes.control.vip")
assert_equal "$VIP" "192.168.100.200"
}
@test "get_current_config with non-existent key" {
NONEXISTENT=$(get_current_config "nonexistent.key")
assert_equal "$NONEXISTENT" ""
}
@test "active nodes configuration access - interface" {
CONTROL_NODE_INTERFACE=$(get_current_config "cluster.nodes.active.\"192.168.100.201\".interface")
assert_equal "$CONTROL_NODE_INTERFACE" "eth0"
}
@test "active nodes configuration access - maintenance IP" {
MAINTENANCE_IP=$(get_current_config "cluster.nodes.active.\"192.168.100.201\".maintenanceIp")
assert_equal "$MAINTENANCE_IP" "192.168.100.131"
}
@test "get_current_secret function" {
# Create temporary secrets file for testing
cp "$TEST_DIR/fixtures/sample-secrets.yaml" "$TEST_PROJECT_DIR/secrets.yaml"
SECRET_VAL=$(get_current_secret "operator.cloudflareApiToken")
assert_equal "$SECRET_VAL" "test_api_token_123456789"
}
@test "config access from subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/config-subdir"
cd "$TEST_PROJECT_DIR/config-subdir"
unset WC_HOME WC_ROOT
init_wild_env
SUBDIR_CLUSTER=$(get_current_config "cluster.name")
assert_equal "$SUBDIR_CLUSTER" "test-cluster"
}

63
test/test_helper.bash Normal file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# test_helper.bash
# Common setup and utilities for bats tests
# Load bats helpers
load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'
# Test environment variables
export TEST_DIR="$(cd "$(dirname "${BATS_TEST_FILENAME}")" && pwd)"
export PROJECT_ROOT="$(dirname "$TEST_DIR")"
export TMP_DIR="$TEST_DIR/tmp"
# Set up test environment
setup_test_project() {
local project_name="${1:-test-project}"
# Create tmp directory
mkdir -p "$TMP_DIR"
# Create test project
export TEST_PROJECT_DIR="$TMP_DIR/$project_name"
mkdir -p "$TEST_PROJECT_DIR/.wildcloud"
# Copy fixture config if it exists
if [ -f "$TEST_DIR/fixtures/sample-config.yaml" ]; then
cp "$TEST_DIR/fixtures/sample-config.yaml" "$TEST_PROJECT_DIR/config.yaml"
fi
# Source wild-common.sh
source "$PROJECT_ROOT/bin/wild-common.sh"
}
# Clean up test environment
teardown_test_project() {
local project_name="${1:-test-project}"
if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then
rm -rf "$TMP_DIR/$project_name"
fi
}
# Create additional test project
create_test_project() {
local project_name="$1"
local project_dir="$TMP_DIR/$project_name"
mkdir -p "$project_dir/.wildcloud"
# Copy fixture config if requested
if [ $# -gt 1 ] && [ "$2" = "with-config" ]; then
cp "$TEST_DIR/fixtures/sample-config.yaml" "$project_dir/config.yaml"
fi
echo "$project_dir"
}
# Remove additional test project
remove_test_project() {
local project_name="$1"
rm -rf "$TMP_DIR/$project_name"
}

View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bats
# test_project_detection.bats
# Tests for wild-cloud project detection from various directory structures
load 'test_helper'
setup() {
setup_test_project "detection-test"
}
teardown() {
teardown_test_project "detection-test"
}
@test "script execution from project root" {
cd "$TEST_PROJECT_DIR"
run "$PROJECT_ROOT/bin/wild-cluster-node-up" --help
assert_success
}
@test "script execution from nested subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/deep/very/nested/path"
cd "$TEST_PROJECT_DIR/deep/very/nested/path"
run "$PROJECT_ROOT/bin/wild-cluster-node-up" --help
assert_success
}
@test "wild-cluster-node-up works from subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/subdir"
cd "$TEST_PROJECT_DIR/subdir"
run "$PROJECT_ROOT/bin/wild-cluster-node-up" --help
assert_success
}
@test "wild-setup works from subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/subdir"
cd "$TEST_PROJECT_DIR/subdir"
run "$PROJECT_ROOT/bin/wild-setup" --help
assert_success
}
@test "wild-setup-cluster works from subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/subdir"
cd "$TEST_PROJECT_DIR/subdir"
run "$PROJECT_ROOT/bin/wild-setup-cluster" --help
assert_success
}
@test "wild-cluster-config-generate works from subdirectory" {
mkdir -p "$TEST_PROJECT_DIR/subdir"
cd "$TEST_PROJECT_DIR/subdir"
run "$PROJECT_ROOT/bin/wild-cluster-config-generate" --help
assert_success
}
@test "config access from subdirectories" {
mkdir -p "$TEST_PROJECT_DIR/config-test"
cd "$TEST_PROJECT_DIR/config-test"
# Set up environment like the scripts do
unset WC_HOME WC_ROOT
init_wild_env
CLUSTER_NAME=$("$PROJECT_ROOT/bin/wild-config" cluster.name 2>/dev/null)
assert_equal "$CLUSTER_NAME" "test-cluster"
}
@test "environment variables from project root" {
cd "$TEST_PROJECT_DIR"
unset WC_HOME WC_ROOT
source "$PROJECT_ROOT/bin/wild-common.sh"
init_wild_env
assert_equal "$WC_HOME" "$TEST_PROJECT_DIR"
assert [ -n "$WC_ROOT" ]
}
@test "environment variables from nested directory" {
mkdir -p "$TEST_PROJECT_DIR/deep/very"
cd "$TEST_PROJECT_DIR/deep/very"
unset WC_HOME WC_ROOT
source "$PROJECT_ROOT/bin/wild-common.sh"
init_wild_env
assert_equal "$WC_HOME" "$TEST_PROJECT_DIR"
assert [ -n "$WC_ROOT" ]
}
@test "scripts fail gracefully outside project" {
# Create a temporary directory without .wildcloud
TEMP_NO_PROJECT=$(create_test_project "no-wildcloud")
rm -rf "$TEMP_NO_PROJECT/.wildcloud"
cd "$TEMP_NO_PROJECT"
# The script should fail because check_wild_directory won't find .wildcloud
run "$PROJECT_ROOT/bin/wild-cluster-node-up" 192.168.1.1 --dry-run
assert_failure
remove_test_project "no-wildcloud"
}