test: add comprehensive tests for WASM functions including registration, stats retrieval, connection status, and message handling

This commit is contained in:
2025-12-30 19:17:43 -06:00
parent 21a0dafae6
commit e51baa8673

174
pkg/wasm/wasm_test.go Normal file
View File

@@ -0,0 +1,174 @@
//go:build js && wasm
// +build js,wasm
package wasm
import (
"encoding/hex"
"fmt"
"syscall/js"
"testing"
"git.quad4.io/Networks/Reticulum-Go/pkg/identity"
)
func TestRegisterJSFunctions(t *testing.T) {
RegisterJSFunctions()
reticulum := js.Global().Get("reticulum")
if reticulum.IsUndefined() {
t.Fatal("reticulum object not registered in global scope")
}
functions := []string{
"init", "getIdentity", "getDestination", "announce",
"connect", "disconnect", "isConnected", "sendMessage", "getStats",
}
for _, fn := range functions {
if reticulum.Get(fn).Type() != js.TypeFunction {
t.Errorf("function %s not registered or not a function", fn)
}
}
}
func TestGetStats(t *testing.T) {
// Reset stats
stats.packetsSent = 10
stats.packetsReceived = 5
stats.bytesSent = 100
stats.bytesReceived = 50
result := GetStats(js.Undefined(), nil)
val := result.(js.Value)
if val.Get("packetsSent").Int() != 10 {
t.Errorf("expected packetsSent 10, got %d", val.Get("packetsSent").Int())
}
if val.Get("packetsReceived").Int() != 5 {
t.Errorf("expected packetsReceived 5, got %d", val.Get("packetsReceived").Int())
}
}
func TestIsConnected(t *testing.T) {
reticulumTransport = nil
connected := IsConnected(js.Undefined(), nil).(js.Value).Bool()
if connected {
t.Error("expected connected to be false when transport is nil")
}
}
func TestInitReticulum(t *testing.T) {
// Mock JS global functions
js.Global().Set("onChatMessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
js.Global().Set("onPeerDiscovered", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
// Test without arguments
result := InitReticulum(js.Undefined(), []js.Value{})
val := result.(js.Value)
if val.Get("error").IsUndefined() || val.Get("error").String() != "WebSocket URL required" {
t.Errorf("expected error 'WebSocket URL required', got %v", val.Get("error"))
}
// Test with valid URL and username
wsURL := "ws://localhost:8080"
username := "testuser"
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(username)})
val = result.(js.Value)
if !val.Get("success").Bool() {
t.Errorf("InitReticulum failed: %v", val.Get("error"))
}
if reticulumIdentity == nil {
t.Fatal("reticulumIdentity should not be nil after successful init")
}
if userName != username {
t.Errorf("expected userName %s, got %s", username, userName)
}
// Test with provided identity
id, _ := identity.NewIdentity()
idHex := id.GetHexHash()
// InitReticulum expects the FULL identity bytes in hex (64 bytes).
idBytes := id.GetPrivateKey()
idHexFull := hex.EncodeToString(idBytes)
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(username), js.ValueOf(idHexFull)})
val = result.(js.Value)
if !val.Get("success").Bool() {
t.Errorf("InitReticulum with identity failed: %v", val.Get("error"))
}
if reticulumIdentity.GetHexHash() != idHex {
t.Errorf("expected identity hash %s, got %s", idHex, reticulumIdentity.GetHexHash())
}
}
func TestIdentityAndDestination(t *testing.T) {
// Ensure initialized
js.Global().Set("onChatMessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
js.Global().Set("onPeerDiscovered", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
idResult := GetIdentity(js.Undefined(), nil).(js.Value)
if idResult.Get("hash").String() != reticulumIdentity.GetHexHash() {
t.Error("GetIdentity returned wrong hash")
}
destResult := GetDestination(js.Undefined(), nil).(js.Value)
expectedDest := fmt.Sprintf("%x", reticulumDest.GetHash())
if destResult.Get("hash").String() != expectedDest {
t.Errorf("GetDestination returned wrong hash, expected %s got %s", expectedDest, destResult.Get("hash").String())
}
}
func TestAnnounce(t *testing.T) {
// Ensure initialized
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
result := SendAnnounce(js.Undefined(), []js.Value{js.ValueOf("new_username")}).(js.Value)
if !result.Get("success").Bool() {
t.Errorf("SendAnnounce failed: %v", result.Get("error"))
}
if userName != "new_username" {
t.Errorf("userName should have been updated to 'new_username', got %s", userName)
}
}
func TestSendMessage(t *testing.T) {
// Ensure initialized
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
// Create a mock peer
peerId, _ := identity.NewIdentity()
peerHash := peerId.Hash()
peerHashHex := hex.EncodeToString(peerHash)
// Manually add to known destinations so Recall works
identity.Remember([]byte("mock_packet"), peerHash, peerId.GetPublicKey(), []byte("peer_app_data"))
// Test SendMessage
msg := "Hello Peer!"
result := SendMessage(js.Undefined(), []js.Value{js.ValueOf(peerHashHex), js.ValueOf(msg)}).(js.Value)
if !result.Get("error").IsUndefined() {
errStr := result.Get("error").String()
if errStr != "Packet sending failed: no path to destination" {
t.Errorf("SendMessage failed with unexpected error: %s", errStr)
} else {
t.Log("SendMessage correctly failed with 'no path to destination' (as expected in test environment)")
}
} else if !result.Get("success").Bool() {
t.Errorf("SendMessage failed without error message")
} else {
if stats.packetsSent != 1 {
t.Errorf("expected 1 packet sent, got %d", stats.packetsSent)
}
}
}