mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
[v3] Fix Linux Desktop Template & Windows NSIS Template Added (#4510)
* feat: added custom protocols to tmpl for windows wails tools * fix:: .Info.Protocols, .Info doesn't exist and causes templater to error * test: tests for build assets * feat: updated changelog * feat: insert macro for custom protocols * Update changelog --------- Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
parent
e2c95ba292
commit
f1037c8e22
5 changed files with 303 additions and 4 deletions
|
|
@ -16,13 +16,15 @@ After processing, the content will be moved to the main changelog and this file
|
|||
-->
|
||||
|
||||
## Added
|
||||
<!-- New features, capabilities, or enhancements -->
|
||||
- Added NSIS Protocol template for Windows by @Tolfx in #4510
|
||||
- Added tests for build-assets by @Tolfx in #4510
|
||||
|
||||
## Changed
|
||||
<!-- Changes in existing functionality -->
|
||||
|
||||
## Fixed
|
||||
<!-- Bug fixes -->
|
||||
- Fixed linux desktop.tmpl protocol range, by removing `<.Info.Protocol>` to `<.Protocol>` by @Tolfx in #4510
|
||||
- Fixed redefinition error for liquid glass demo in [#4542](https://github.com/wailsapp/wails/pull/4542) by @Etesam913
|
||||
|
||||
## Deprecated
|
||||
<!-- Soon-to-be removed features -->
|
||||
|
|
|
|||
267
v3/internal/commands/build-assets_test.go
Normal file
267
v3/internal/commands/build-assets_test.go
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestGenerateBuildAssets(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir, err := os.MkdirTemp("", "wails-build-assets-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
options *BuildAssetsOptions
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Basic build assets generation",
|
||||
options: &BuildAssetsOptions{
|
||||
Dir: "testbuild",
|
||||
Name: "TestApp",
|
||||
BinaryName: "",
|
||||
ProductName: "Test Application",
|
||||
ProductDescription: "A test application",
|
||||
ProductVersion: "1.0.0",
|
||||
ProductCompany: "Test Company",
|
||||
ProductCopyright: "© 2024 Test Company",
|
||||
ProductComments: "Test comments",
|
||||
ProductIdentifier: "",
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Build assets with custom binary name",
|
||||
options: &BuildAssetsOptions{
|
||||
Dir: "testbuild2",
|
||||
Name: "Custom App",
|
||||
BinaryName: "custom-binary",
|
||||
ProductName: "Custom Application",
|
||||
ProductDescription: "A custom application",
|
||||
ProductVersion: "2.0.0",
|
||||
ProductCompany: "Custom Company",
|
||||
ProductIdentifier: "com.custom.app",
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Build assets with MSIX options",
|
||||
options: &BuildAssetsOptions{
|
||||
Dir: "testbuild3",
|
||||
Name: "MSIX App",
|
||||
ProductName: "MSIX Application",
|
||||
ProductDescription: "An MSIX application",
|
||||
ProductVersion: "3.0.0",
|
||||
ProductCompany: "MSIX Company",
|
||||
Publisher: "CN=MSIX Company",
|
||||
ProcessorArchitecture: "x64",
|
||||
ExecutablePath: "msix-app.exe",
|
||||
ExecutableName: "msix-app.exe",
|
||||
OutputPath: "msix-app.msix",
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Build assets with TypeScript",
|
||||
options: &BuildAssetsOptions{
|
||||
Dir: "testbuild4",
|
||||
Name: "TypeScript App",
|
||||
ProductName: "TypeScript Application",
|
||||
ProductDescription: "A TypeScript application",
|
||||
ProductVersion: "4.0.0",
|
||||
ProductCompany: "TypeScript Company",
|
||||
Typescript: true,
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set the directory to be under our temp directory
|
||||
buildDir := filepath.Join(tempDir, tt.options.Dir)
|
||||
tt.options.Dir = buildDir
|
||||
|
||||
err := GenerateBuildAssets(tt.options)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GenerateBuildAssets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
// Verify that the build directory was created
|
||||
if _, err := os.Stat(buildDir); os.IsNotExist(err) {
|
||||
t.Errorf("Build directory %s was not created", buildDir)
|
||||
}
|
||||
|
||||
// List all files that were actually created for debugging
|
||||
files, err := os.ReadDir(buildDir)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to read build directory: %v", err)
|
||||
} else {
|
||||
t.Logf("Files created in %s:", buildDir)
|
||||
for _, file := range files {
|
||||
t.Logf(" - %s", file.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// Verify some expected files were created - check what actually exists
|
||||
expectedFiles := []string{
|
||||
"config.yml",
|
||||
"appicon.png",
|
||||
"Taskfile.yml",
|
||||
}
|
||||
|
||||
for _, file := range expectedFiles {
|
||||
filePath := filepath.Join(buildDir, file)
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
t.Errorf("Expected file %s was not created", file)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that defaults were applied correctly
|
||||
if tt.options.ProductIdentifier == "" && tt.options.Name != "" {
|
||||
expectedIdentifier := "com.wails." + normaliseName(tt.options.Name)
|
||||
// We can't easily check this without modifying the function to return the config
|
||||
// but we know the logic is there
|
||||
_ = expectedIdentifier
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateBuildAssets(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir, err := os.MkdirTemp("", "wails-update-assets-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
// Create a sample wails config file
|
||||
configDir := filepath.Join(tempDir, "config")
|
||||
err = os.MkdirAll(configDir, 0755)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create config directory: %v", err)
|
||||
}
|
||||
|
||||
configFile := filepath.Join(configDir, "wails.yaml")
|
||||
config := WailsConfig{
|
||||
Info: struct {
|
||||
CompanyName string `yaml:"companyName"`
|
||||
ProductName string `yaml:"productName"`
|
||||
ProductIdentifier string `yaml:"productIdentifier"`
|
||||
Description string `yaml:"description"`
|
||||
Copyright string `yaml:"copyright"`
|
||||
Comments string `yaml:"comments"`
|
||||
Version string `yaml:"version"`
|
||||
}{
|
||||
CompanyName: "Config Company",
|
||||
ProductName: "Config Product",
|
||||
ProductIdentifier: "com.config.product",
|
||||
Description: "Config Description",
|
||||
Copyright: "© 2024 Config Company",
|
||||
Comments: "Config Comments",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
FileAssociations: []FileAssociation{
|
||||
{
|
||||
Ext: ".test",
|
||||
Name: "Test File",
|
||||
Description: "Test file association",
|
||||
IconName: "test-icon",
|
||||
Role: "Editor",
|
||||
MimeType: "application/test",
|
||||
},
|
||||
},
|
||||
Protocols: []ProtocolConfig{
|
||||
{
|
||||
Scheme: "testapp",
|
||||
Description: "Test App Protocol",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
configBytes, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal config: %v", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(configFile, configBytes, 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write config file: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
options *UpdateBuildAssetsOptions
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Update with config file",
|
||||
options: &UpdateBuildAssetsOptions{
|
||||
Dir: "updatebuild1",
|
||||
Name: "UpdateApp",
|
||||
Config: configFile,
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update without config file",
|
||||
options: &UpdateBuildAssetsOptions{
|
||||
Dir: "updatebuild2",
|
||||
Name: "UpdateApp2",
|
||||
ProductName: "Update Application 2",
|
||||
ProductDescription: "An update application 2",
|
||||
ProductVersion: "2.0.0",
|
||||
ProductCompany: "Update Company 2",
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update with non-existent config file",
|
||||
options: &UpdateBuildAssetsOptions{
|
||||
Dir: "updatebuild3",
|
||||
Name: "UpdateApp3",
|
||||
Config: "non-existent-config.yaml",
|
||||
Silent: true,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set the directory to be under our temp directory
|
||||
updateDir := filepath.Join(tempDir, tt.options.Dir)
|
||||
tt.options.Dir = updateDir
|
||||
|
||||
err := UpdateBuildAssets(tt.options)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("UpdateBuildAssets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
// Verify that the update directory was created
|
||||
if _, err := os.Stat(updateDir); os.IsNotExist(err) {
|
||||
t.Errorf("Update directory %s was not created", updateDir)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,8 @@ Section
|
|||
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
|
||||
|
||||
!insertmacro wails.associateFiles
|
||||
|
||||
!insertmacro wails.associateCustomProtocols
|
||||
|
||||
!insertmacro wails.writeUninstaller
|
||||
SectionEnd
|
||||
|
||||
|
|
@ -107,6 +108,7 @@ Section "uninstall"
|
|||
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
|
||||
|
||||
!insertmacro wails.unassociateFiles
|
||||
!insertmacro wails.unassociateCustomProtocols
|
||||
|
||||
!insertmacro wails.deleteUninstaller
|
||||
SectionEnd
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ Categories=Utility;
|
|||
StartupWMClass={{.BinaryName}}
|
||||
|
||||
{{if .Protocols -}}
|
||||
MimeType={{range $index, $protocol := .Info.Protocols}}x-scheme-handler/{{$protocol.Scheme}};{{end}}
|
||||
MimeType={{range $index, $protocol := .Protocols}}x-scheme-handler/{{$protocol.Scheme}};{{end}}
|
||||
{{- end}}
|
||||
|
|
|
|||
|
|
@ -215,4 +215,32 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
|
|||
!insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
|
||||
Delete "$INSTDIR\{{.IconName}}.ico"
|
||||
{{end}}
|
||||
!macroend
|
||||
|
||||
!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
|
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
|
||||
!macroend
|
||||
|
||||
!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
|
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
|
||||
!macroend
|
||||
|
||||
!macro wails.associateCustomProtocols
|
||||
; Create custom protocols associations
|
||||
{{range .Protocols}}
|
||||
!insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
|
||||
{{end}}
|
||||
!macroend
|
||||
|
||||
!macro wails.unassociateCustomProtocols
|
||||
; Delete app custom protocol associations
|
||||
{{range .Protocols}}
|
||||
!insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}"
|
||||
{{end}}
|
||||
!macroend
|
||||
Loading…
Add table
Add a link
Reference in a new issue