hako/e2e/e2eutil/container.go
Felipe M. f47010cd0f
Some checks failed
CI / goreleaser-lint (pull_request) Successful in 11s
CI / format (pull_request) Successful in 2m38s
CI / test (pull_request) Successful in 5m0s
CI / lint (pull_request) Successful in 3m5s
CI / build (pull_request) Successful in 3m16s
CI / e2e (pull_request) Failing after 28m15s
fix(e2e): make link creation reach test web server via shared network
The test web server and Hako container previously ran on isolated Docker
networks, so Hako could not fetch URLs like http://localhost:32865 (the
host-mapped port) from inside its container. Most tests passed vacuously
because they only checked DOM containers; the Archive tests failed
because they tried to click an actual link item that was never created.

Changes:
- Add a shared Docker network so both containers can communicate by alias
- Test web server registers as hako-testserver and returns that as its URL
- Hako container joins the same network and can resolve the alias
- CreateLink now navigates to /home before each call so it can be invoked
  multiple times in a row (the form redirects to /links after submission)
- IsVisible uses .First() to avoid Playwright strict-mode errors when a
  selector matches multiple elements
- Archive tests use .link-item instead of the never-matching
  a[href*='/links/'] selector
- Bump Dockerfile.e2e Alpine to 3.23 to match the production Containerfile
2026-04-08 16:42:42 +02:00

109 lines
3.1 KiB
Go

package e2eutil
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
"github.com/docker/go-connections/nat"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
// StartHakoContainer starts a Hako container for E2E testing.
// It builds the webapp, compiles the binary, creates a container, and returns
// the container instance and base URL for accessing the server.
func StartHakoContainer(ctx context.Context, t *testing.T) (testcontainers.Container, string, error) {
t.Helper()
// Get the project root (one level up from e2e)
projectRoot, err := filepath.Abs(filepath.Join("..", ".."))
if err != nil {
return nil, "", fmt.Errorf("failed to get project root: %w", err)
}
// Build webapp
t.Log("Building webapp...")
cmd := exec.CommandContext(ctx, "make", "build-webapp")
cmd.Dir = projectRoot
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, "", fmt.Errorf("failed to build webapp: %w", err)
}
// Build Hako binary for the container (Linux)
t.Log("Building Hako binary...")
binaryPath := filepath.Join(projectRoot, "e2e", "hako")
cmd = exec.CommandContext(ctx, "go", "build", "-o", binaryPath, "./cmd/hako")
cmd.Dir = projectRoot
cmd.Env = append(os.Environ(), "CGO_ENABLED=0", "GOOS=linux", "GOARCH=amd64")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, "", fmt.Errorf("failed to build binary: %w", err)
}
// Ensure binary is removed on cleanup
t.Cleanup(func() {
os.Remove(binaryPath)
})
// Ensure shared network exists so Hako can reach the test web server by alias.
nw, err := getSharedNetwork(ctx)
if err != nil {
return nil, "", err
}
// Create container request attached to the shared network.
req := testcontainers.ContainerRequest{
FromDockerfile: testcontainers.FromDockerfile{
Context: filepath.Join(projectRoot, "e2e"),
Dockerfile: "Dockerfile.e2e",
PrintBuildLog: true,
},
ExposedPorts: []string{"8080/tcp"},
WaitingFor: wait.ForLog("Starting HTTP server").
WithStartupTimeout(30 * time.Second),
Networks: []string{nw.Name},
}
// Start container
t.Log("Starting Hako container...")
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
if err != nil {
return nil, "", fmt.Errorf("failed to start container: %w", err)
}
// Register cleanup
t.Cleanup(func() {
if err := container.Terminate(ctx); err != nil {
t.Logf("Failed to terminate container: %v", err)
}
})
// Get the mapped port
mappedPort, err := container.MappedPort(ctx, nat.Port("8080/tcp"))
if err != nil {
return nil, "", fmt.Errorf("failed to get mapped port: %w", err)
}
// Get the host
host, err := container.Host(ctx)
if err != nil {
return nil, "", fmt.Errorf("failed to get container host: %w", err)
}
// Construct base URL
baseURL := fmt.Sprintf("http://%s:%s", host, mappedPort.Port())
t.Logf("Hako container started at %s", baseURL)
return container, baseURL, nil
}