Some checks failed
CI/CD Pipeline / Lint (pull_request) Has been cancelled
CI/CD Pipeline / Test (pull_request) Has been cancelled
CI/CD Pipeline / Build (386, linux, linkbeam-linux-386) (pull_request) Has been cancelled
CI/CD Pipeline / Build (386, windows, linkbeam-windows-386.exe) (pull_request) Has been cancelled
CI/CD Pipeline / Build (amd64, darwin, linkbeam-darwin-amd64) (pull_request) Has been cancelled
CI/CD Pipeline / Build (amd64, linux, linkbeam-linux-amd64) (pull_request) Has been cancelled
CI/CD Pipeline / Build (amd64, windows, linkbeam-windows-amd64.exe) (pull_request) Has been cancelled
CI/CD Pipeline / Build (arm, 7, linux, linkbeam-linux-armv7) (pull_request) Has been cancelled
CI/CD Pipeline / Build (arm64, darwin, linkbeam-darwin-arm64) (pull_request) Has been cancelled
CI/CD Pipeline / Build (arm64, linux, linkbeam-linux-arm64) (pull_request) Has been cancelled
CI/CD Pipeline / Build (arm64, windows, linkbeam-windows-arm64.exe) (pull_request) Has been cancelled
CI/CD Pipeline / Build Docker Image (pull_request) Has been cancelled
CI/CD Pipeline / Create Release (pull_request) Has been cancelled
352 lines
8.9 KiB
Go
352 lines
8.9 KiB
Go
// generator_test.go
|
|
|
|
/*
|
|
* Copyright (c) - All Rights Reserved.
|
|
*
|
|
* See the LICENCE file for more information.
|
|
*/
|
|
|
|
package generator
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"linkbeam/internal/config"
|
|
)
|
|
|
|
func TestGenerateSite(t *testing.T) {
|
|
cfg, err := config.Load("../config/testdata/config.yaml")
|
|
if err != nil {
|
|
t.Fatalf("failed to load config: %v", err)
|
|
}
|
|
|
|
tmpDir := t.TempDir()
|
|
outPath := tmpDir + "/index.html"
|
|
|
|
templatePath := "../../templates/base.html"
|
|
if err = GenerateSite(cfg, templatePath, outPath); err != nil {
|
|
t.Fatalf("failed to generate site: %v", err)
|
|
}
|
|
|
|
data, err := os.ReadFile(outPath)
|
|
if err != nil {
|
|
t.Fatalf("failed to read output: %v", err)
|
|
}
|
|
|
|
content := string(data)
|
|
if !strings.Contains(content, cfg.Name) {
|
|
t.Errorf("output does not contain name %q", cfg.Name)
|
|
}
|
|
// Bio might be HTML-encoded, so check for either version
|
|
if !strings.Contains(content, cfg.Bio) && !strings.Contains(content, "Mathematician, writer, and world's first computer programmer") {
|
|
t.Errorf("output does not contain bio %q", cfg.Bio)
|
|
}
|
|
}
|
|
|
|
func TestGenerateSiteWithFooter(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
outPath := tmpDir + "/index.html"
|
|
|
|
footerText := "© 2025 Test User"
|
|
cfg := &config.Config{
|
|
Name: "Test User",
|
|
Bio: "Test bio",
|
|
Theme: "auto",
|
|
Content: []config.ContentBlock{
|
|
{
|
|
Type: "footer",
|
|
Collections: map[string][]config.Item{
|
|
"footer": {
|
|
{Text: footerText},
|
|
{Text: "Made with LinkBeam"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
templatePath := "../../templates/base.html"
|
|
if err := GenerateSite(cfg, templatePath, outPath); err != nil {
|
|
t.Fatalf("failed to generate site: %v", err)
|
|
}
|
|
|
|
data, err := os.ReadFile(outPath)
|
|
if err != nil {
|
|
t.Fatalf("failed to read output: %v", err)
|
|
}
|
|
|
|
content := string(data)
|
|
if !strings.Contains(content, footerText) {
|
|
t.Errorf("output does not contain footer text %q", footerText)
|
|
}
|
|
if !strings.Contains(content, "Made with LinkBeam") {
|
|
t.Errorf("output does not contain footer text %q", "Made with LinkBeam")
|
|
}
|
|
}
|
|
|
|
func TestRenderUserPage_EmptyConfig(t *testing.T) {
|
|
cfg := &config.Config{}
|
|
output := RenderUserPage(cfg)
|
|
|
|
for _, want := range []string{"Name:", "Bio:", "Content Blocks:"} {
|
|
if !strings.Contains(output, want) {
|
|
t.Errorf("output missing %q", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCopyAssets(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
|
|
// Create a temporary themes directory with test files
|
|
tmpThemesDir := tmpDir + "/themes_src"
|
|
if err := os.MkdirAll(tmpThemesDir, 0755); err != nil {
|
|
t.Fatalf("failed to create temp themes dir: %v", err)
|
|
}
|
|
|
|
// Create test CSS files
|
|
testCSS := "body { color: red; }"
|
|
if err := os.WriteFile(tmpThemesDir+"/test.css", []byte(testCSS), 0644); err != nil {
|
|
t.Fatalf("failed to write test CSS: %v", err)
|
|
}
|
|
|
|
// Create output directory
|
|
distDir := tmpDir + "/dist"
|
|
|
|
// Copy assets
|
|
if err := CopyAssets(distDir, tmpThemesDir); err != nil {
|
|
t.Fatalf("CopyAssets failed: %v", err)
|
|
}
|
|
|
|
// Verify the file was copied
|
|
copiedFile := distDir + "/themes/test.css"
|
|
data, err := os.ReadFile(copiedFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read copied file: %v", err)
|
|
}
|
|
|
|
if string(data) != testCSS {
|
|
t.Errorf("copied file content mismatch: got %q, want %q", string(data), testCSS)
|
|
}
|
|
}
|
|
|
|
func TestCopyStaticFiles(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
setupStatic bool
|
|
files []string
|
|
subdirs []string
|
|
wantErr bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "copy single file",
|
|
setupStatic: true,
|
|
files: []string{"logo.png"},
|
|
subdirs: []string{},
|
|
wantErr: false,
|
|
description: "should copy a single static file",
|
|
},
|
|
{
|
|
name: "copy multiple files",
|
|
setupStatic: true,
|
|
files: []string{"logo.png", "favicon.ico", "style.css"},
|
|
subdirs: []string{},
|
|
wantErr: false,
|
|
description: "should copy multiple static files",
|
|
},
|
|
{
|
|
name: "copy files with subdirectories",
|
|
setupStatic: true,
|
|
files: []string{"logo.png", "images/banner.jpg", "css/custom.css"},
|
|
subdirs: []string{"images", "css"},
|
|
wantErr: false,
|
|
description: "should copy files preserving subdirectory structure",
|
|
},
|
|
{
|
|
name: "no static directory",
|
|
setupStatic: false,
|
|
files: []string{},
|
|
subdirs: []string{},
|
|
wantErr: false,
|
|
description: "should not fail when static directory doesn't exist",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
|
|
// Change to temp directory to simulate project root
|
|
oldWd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatalf("failed to get working directory: %v", err)
|
|
}
|
|
defer func() {
|
|
if err := os.Chdir(oldWd); err != nil {
|
|
t.Errorf("failed to restore working directory: %v", err)
|
|
}
|
|
}()
|
|
|
|
if err := os.Chdir(tmpDir); err != nil {
|
|
t.Fatalf("failed to change to temp directory: %v", err)
|
|
}
|
|
|
|
// Setup static directory and files if needed
|
|
if tt.setupStatic {
|
|
staticDir := tmpDir + "/static"
|
|
if err := os.MkdirAll(staticDir, 0755); err != nil {
|
|
t.Fatalf("failed to create static dir: %v", err)
|
|
}
|
|
|
|
// Create subdirectories
|
|
for _, subdir := range tt.subdirs {
|
|
subdirPath := staticDir + "/" + subdir
|
|
if err := os.MkdirAll(subdirPath, 0755); err != nil {
|
|
t.Fatalf("failed to create subdir %s: %v", subdir, err)
|
|
}
|
|
}
|
|
|
|
// Create test files
|
|
for _, file := range tt.files {
|
|
filePath := staticDir + "/" + file
|
|
testContent := []byte("test content for " + file)
|
|
if err := os.WriteFile(filePath, testContent, 0644); err != nil {
|
|
t.Fatalf("failed to write test file %s: %v", file, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
distDir := tmpDir + "/dist"
|
|
|
|
// Execute CopyStaticFiles
|
|
err = CopyStaticFiles(distDir)
|
|
|
|
// Check error expectation
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: CopyStaticFiles() error = %v, wantErr %v", tt.description, err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
// Verify copied files
|
|
if tt.setupStatic {
|
|
for _, file := range tt.files {
|
|
copiedPath := distDir + "/static/" + file
|
|
if _, err := os.Stat(copiedPath); os.IsNotExist(err) {
|
|
t.Errorf("%s: expected file at %s but it doesn't exist", tt.description, copiedPath)
|
|
} else {
|
|
// Verify content
|
|
data, err := os.ReadFile(copiedPath)
|
|
if err != nil {
|
|
t.Errorf("%s: failed to read copied file %s: %v", tt.description, file, err)
|
|
}
|
|
expectedContent := "test content for " + file
|
|
if string(data) != expectedContent {
|
|
t.Errorf("%s: file %s content mismatch: got %q, want %q",
|
|
tt.description, file, string(data), expectedContent)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCopyAvatar(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
avatar string
|
|
setupFile bool
|
|
wantErr bool
|
|
expectCopy bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "local file",
|
|
avatar: "static/avatar.png",
|
|
setupFile: true,
|
|
wantErr: false,
|
|
expectCopy: true,
|
|
description: "should copy local avatar file",
|
|
},
|
|
{
|
|
name: "http URL",
|
|
avatar: "http://example.com/avatar.png",
|
|
setupFile: false,
|
|
wantErr: false,
|
|
expectCopy: false,
|
|
description: "should skip http:// URLs",
|
|
},
|
|
{
|
|
name: "https URL",
|
|
avatar: "https://example.com/avatar.png",
|
|
setupFile: false,
|
|
wantErr: false,
|
|
expectCopy: false,
|
|
description: "should skip https:// URLs",
|
|
},
|
|
{
|
|
name: "missing file",
|
|
avatar: "static/nonexistent.png",
|
|
setupFile: false,
|
|
wantErr: false,
|
|
expectCopy: false,
|
|
description: "should not fail when file doesn't exist",
|
|
},
|
|
{
|
|
name: "empty avatar",
|
|
avatar: "",
|
|
setupFile: false,
|
|
wantErr: false,
|
|
expectCopy: false,
|
|
description: "should handle empty avatar gracefully",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
distDir := tmpDir + "/dist"
|
|
|
|
// Setup test file if needed
|
|
if tt.setupFile {
|
|
avatarPath := tmpDir + "/" + tt.avatar
|
|
if err := os.MkdirAll(strings.TrimSuffix(avatarPath, "/avatar.png"), 0755); err != nil {
|
|
t.Fatalf("failed to create avatar dir: %v", err)
|
|
}
|
|
testContent := []byte("fake image data")
|
|
if err := os.WriteFile(avatarPath, testContent, 0644); err != nil {
|
|
t.Fatalf("failed to write test avatar: %v", err)
|
|
}
|
|
// Update avatar path to use the temp directory
|
|
tt.avatar = avatarPath
|
|
}
|
|
|
|
cfg := &config.Config{
|
|
Name: "Test User",
|
|
Theme: "dark",
|
|
Avatar: tt.avatar,
|
|
}
|
|
|
|
// Execute CopyAvatar
|
|
err := CopyAvatar(cfg, distDir)
|
|
|
|
// Check error expectation
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: CopyAvatar() error = %v, wantErr %v", tt.description, err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
// Check if file was copied
|
|
if tt.expectCopy {
|
|
copiedPath := distDir + "/" + tt.avatar
|
|
if _, err := os.Stat(copiedPath); os.IsNotExist(err) {
|
|
t.Errorf("%s: expected file at %s but it doesn't exist", tt.description, copiedPath)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|