mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-15 23:25:49 +01:00
Allow users to pass custom build tags via `wails3 build -tags gtk4` instead of requiring Taskfile modifications. Tags are forwarded as EXTRA_TAGS to platform Taskfiles and appended to the go build command alongside the existing production tag. Works for both native and Docker cross-compilation builds. Closes #4957 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
440 lines
12 KiB
Go
440 lines
12 KiB
Go
package commands
|
|
|
|
import (
|
|
"os"
|
|
"runtime"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/wailsapp/wails/v3/internal/flags"
|
|
)
|
|
|
|
func TestWrapTask(t *testing.T) {
|
|
// Get current platform info for expected values
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
tests := []struct {
|
|
name string
|
|
command string
|
|
otherArgs []string
|
|
envGOOS string
|
|
envGOARCH string
|
|
expectedTaskName string
|
|
expectedArgs []string
|
|
expectedOsArgs []string
|
|
}{
|
|
{
|
|
name: "Build with parameters uses current platform",
|
|
command: "build",
|
|
otherArgs: []string{"CONFIG=debug"},
|
|
expectedTaskName: currentOS + ":build",
|
|
expectedArgs: []string{"CONFIG=debug", "ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "CONFIG=debug", "ARCH=" + currentArch},
|
|
},
|
|
{
|
|
name: "Package with parameters uses current platform",
|
|
command: "package",
|
|
otherArgs: []string{"VERSION=1.0.0", "OUTPUT=app.pkg"},
|
|
expectedTaskName: currentOS + ":package",
|
|
expectedArgs: []string{"VERSION=1.0.0", "OUTPUT=app.pkg", "ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", currentOS + ":package", "VERSION=1.0.0", "OUTPUT=app.pkg", "ARCH=" + currentArch},
|
|
},
|
|
{
|
|
name: "Build without parameters",
|
|
command: "build",
|
|
otherArgs: []string{},
|
|
expectedTaskName: currentOS + ":build",
|
|
expectedArgs: []string{"ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "ARCH=" + currentArch},
|
|
},
|
|
{
|
|
name: "GOOS override changes task prefix",
|
|
command: "build",
|
|
otherArgs: []string{"GOOS=darwin", "CONFIG=release"},
|
|
expectedTaskName: "darwin:build",
|
|
expectedArgs: []string{"CONFIG=release", "ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", "darwin:build", "CONFIG=release", "ARCH=" + currentArch},
|
|
},
|
|
{
|
|
name: "GOARCH override changes ARCH arg",
|
|
command: "build",
|
|
otherArgs: []string{"GOARCH=arm64"},
|
|
expectedTaskName: currentOS + ":build",
|
|
expectedArgs: []string{"ARCH=arm64"},
|
|
expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "ARCH=arm64"},
|
|
},
|
|
{
|
|
name: "Both GOOS and GOARCH override",
|
|
command: "package",
|
|
otherArgs: []string{"GOOS=windows", "GOARCH=386", "VERSION=2.0"},
|
|
expectedTaskName: "windows:package",
|
|
expectedArgs: []string{"VERSION=2.0", "ARCH=386"},
|
|
expectedOsArgs: []string{"wails3", "task", "windows:package", "VERSION=2.0", "ARCH=386"},
|
|
},
|
|
{
|
|
name: "Environment GOOS is used when no arg override",
|
|
command: "build",
|
|
otherArgs: []string{"CONFIG=debug"},
|
|
envGOOS: "darwin",
|
|
expectedTaskName: "darwin:build",
|
|
expectedArgs: []string{"CONFIG=debug", "ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", "darwin:build", "CONFIG=debug", "ARCH=" + currentArch},
|
|
},
|
|
{
|
|
name: "Arg GOOS overrides environment GOOS",
|
|
command: "build",
|
|
otherArgs: []string{"GOOS=linux"},
|
|
envGOOS: "darwin",
|
|
expectedTaskName: "linux:build",
|
|
expectedArgs: []string{"ARCH=" + currentArch},
|
|
expectedOsArgs: []string{"wails3", "task", "linux:build", "ARCH=" + currentArch},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save and restore os.Args
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
// Save and restore environment variables
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
|
|
// Set test environment
|
|
if tt.envGOOS != "" {
|
|
os.Setenv("GOOS", tt.envGOOS)
|
|
} else {
|
|
os.Unsetenv("GOOS")
|
|
}
|
|
if tt.envGOARCH != "" {
|
|
os.Setenv("GOARCH", tt.envGOARCH)
|
|
} else {
|
|
os.Unsetenv("GOARCH")
|
|
}
|
|
|
|
// Mock RunTask to capture the arguments
|
|
originalRunTask := runTaskFunc
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Execute wrapTask
|
|
err := wrapTask(tt.command, tt.otherArgs)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify os.Args was set correctly
|
|
assert.Equal(t, tt.expectedOsArgs, os.Args)
|
|
|
|
// Verify RunTask was called with correct parameters
|
|
assert.Equal(t, tt.expectedTaskName, capturedOptions.Name)
|
|
assert.Equal(t, tt.expectedArgs, capturedOtherArgs)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildCommand(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test Build command
|
|
buildFlags := &flags.Build{}
|
|
otherArgs := []string{"CONFIG=release"}
|
|
|
|
err := Build(buildFlags, otherArgs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":build", capturedOptions.Name)
|
|
assert.Equal(t, []string{"CONFIG=release", "ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|
|
|
|
func TestBuildCommandWithTags(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test Build command with tags
|
|
buildFlags := &flags.Build{}
|
|
buildFlags.Tags = "gtk4"
|
|
otherArgs := []string{"CONFIG=release"}
|
|
|
|
err := Build(buildFlags, otherArgs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":build", capturedOptions.Name)
|
|
assert.Equal(t, []string{"CONFIG=release", "EXTRA_TAGS=gtk4", "ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|
|
|
|
func TestBuildCommandWithMultipleTags(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test Build command with multiple comma-separated tags
|
|
buildFlags := &flags.Build{}
|
|
buildFlags.Tags = "gtk4,server"
|
|
|
|
err := Build(buildFlags, nil)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":build", capturedOptions.Name)
|
|
assert.Equal(t, []string{"EXTRA_TAGS=gtk4,server", "ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|
|
|
|
func TestBuildCommandWithoutTags(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test Build command without tags - no EXTRA_TAGS should be present
|
|
buildFlags := &flags.Build{}
|
|
|
|
err := Build(buildFlags, nil)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":build", capturedOptions.Name)
|
|
assert.Equal(t, []string{"ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|
|
|
|
func TestPackageCommand(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test Package command
|
|
packageFlags := &flags.Package{}
|
|
otherArgs := []string{"VERSION=2.0.0", "OUTPUT=myapp.dmg"}
|
|
|
|
err := Package(packageFlags, otherArgs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":package", capturedOptions.Name)
|
|
assert.Equal(t, []string{"VERSION=2.0.0", "OUTPUT=myapp.dmg", "ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|
|
|
|
func TestSignWrapperCommand(t *testing.T) {
|
|
currentOS := runtime.GOOS
|
|
currentArch := runtime.GOARCH
|
|
|
|
// Save original RunTask
|
|
originalRunTask := runTaskFunc
|
|
defer func() { runTaskFunc = originalRunTask }()
|
|
|
|
// Mock RunTask to capture the arguments
|
|
var capturedOptions *RunTaskOptions
|
|
var capturedOtherArgs []string
|
|
runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error {
|
|
capturedOptions = options
|
|
capturedOtherArgs = otherArgs
|
|
return nil
|
|
}
|
|
|
|
// Save original os.Args and environment
|
|
originalArgs := os.Args
|
|
defer func() { os.Args = originalArgs }()
|
|
|
|
originalGOOS := os.Getenv("GOOS")
|
|
originalGOARCH := os.Getenv("GOARCH")
|
|
defer func() {
|
|
if originalGOOS == "" {
|
|
os.Unsetenv("GOOS")
|
|
} else {
|
|
os.Setenv("GOOS", originalGOOS)
|
|
}
|
|
if originalGOARCH == "" {
|
|
os.Unsetenv("GOARCH")
|
|
} else {
|
|
os.Setenv("GOARCH", originalGOARCH)
|
|
}
|
|
}()
|
|
os.Unsetenv("GOOS")
|
|
os.Unsetenv("GOARCH")
|
|
|
|
// Test SignWrapper command
|
|
signFlags := &flags.SignWrapper{}
|
|
otherArgs := []string{"IDENTITY=Developer ID"}
|
|
|
|
err := SignWrapper(signFlags, otherArgs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, currentOS+":sign", capturedOptions.Name)
|
|
assert.Equal(t, []string{"IDENTITY=Developer ID", "ARCH=" + currentArch}, capturedOtherArgs)
|
|
}
|