From 84ec5c212c1b941e1ff2350e6ab37a69d4a2d542 Mon Sep 17 00:00:00 2001
From: Jono Wenger <jono@elixxir.io>
Date: Fri, 9 Sep 2022 18:15:56 -0700
Subject: [PATCH] Add tests that check that wasm objects have the same methods
 as their bindings counterparts

---
 wasm/authenticatedConnection_test.go | 21 ++++++++++++
 wasm/backup_test.go                  | 20 +++++++++++
 wasm/broadcast_test.go               | 20 +++++++++++
 wasm/cmix_test.go                    | 20 +++++++++++
 wasm/connect_test.go                 | 20 +++++++++++
 wasm/e2e_test.go                     | 20 +++++++++++
 wasm/fileTransfer_test.go            | 41 +++++++++++++++++++++++
 wasm/follow.go                       | 26 ++++++++++++++-
 wasm/group_test.go                   | 50 +++++++++++++++++++++++++---
 wasm/single_test.go                  | 21 ++++++++++++
 wasm/ud_test.go                      | 21 ++++++++++++
 11 files changed, 274 insertions(+), 6 deletions(-)

diff --git a/wasm/authenticatedConnection_test.go b/wasm/authenticatedConnection_test.go
index b618514b..a50eaf12 100644
--- a/wasm/authenticatedConnection_test.go
+++ b/wasm/authenticatedConnection_test.go
@@ -35,3 +35,24 @@ func Test_newAuthenticatedConnectionJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that AuthenticatedConnection has all the methods that
+// [bindings.AuthenticatedConnection] has.
+func Test_AuthenticatedConnectionMethods(t *testing.T) {
+	authType := reflect.TypeOf(&AuthenticatedConnection{})
+	binAuthType := reflect.TypeOf(&bindings.AuthenticatedConnection{})
+
+	if binAuthType.NumMethod() != authType.NumMethod() {
+		t.Errorf("WASM AuthenticatedConnection object does not have all "+
+			"methods from bindings.\nexpected: %d\nreceived: %d",
+			binAuthType.NumMethod(), authType.NumMethod())
+	}
+
+	for i := 0; i < binAuthType.NumMethod(); i++ {
+		method := binAuthType.Method(i)
+
+		if _, exists := authType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/backup_test.go b/wasm/backup_test.go
index 4782f0e1..8946fc6a 100644
--- a/wasm/backup_test.go
+++ b/wasm/backup_test.go
@@ -32,3 +32,23 @@ func Test_newBackupJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that Backup has all the methods that [bindings.Backup] has.
+func Test_BackupMethods(t *testing.T) {
+	backupType := reflect.TypeOf(&Backup{})
+	binBackupType := reflect.TypeOf(&bindings.Backup{})
+
+	if binBackupType.NumMethod() != backupType.NumMethod() {
+		t.Errorf("WASM Backup object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binBackupType.NumMethod(), backupType.NumMethod())
+	}
+
+	for i := 0; i < binBackupType.NumMethod(); i++ {
+		method := binBackupType.Method(i)
+
+		if _, exists := backupType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/broadcast_test.go b/wasm/broadcast_test.go
index 4dc46883..3541c5c0 100644
--- a/wasm/broadcast_test.go
+++ b/wasm/broadcast_test.go
@@ -34,3 +34,23 @@ func Test_newChannelJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that Channel has all the methods that [bindings.Channel] has.
+func Test_ChannelMethods(t *testing.T) {
+	chanType := reflect.TypeOf(&Channel{})
+	binChanType := reflect.TypeOf(&bindings.Channel{})
+
+	if binChanType.NumMethod() != chanType.NumMethod() {
+		t.Errorf("WASM Channel object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binChanType.NumMethod(), chanType.NumMethod())
+	}
+
+	for i := 0; i < binChanType.NumMethod(); i++ {
+		method := binChanType.Method(i)
+
+		if _, exists := chanType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/cmix_test.go b/wasm/cmix_test.go
index 316b1508..703440b4 100644
--- a/wasm/cmix_test.go
+++ b/wasm/cmix_test.go
@@ -35,3 +35,23 @@ func Test_newCmixJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that Cmix has all the methods that [bindings.Cmix] has.
+func Test_CmixMethods(t *testing.T) {
+	cmixType := reflect.TypeOf(&Cmix{})
+	binCmixType := reflect.TypeOf(&bindings.Cmix{})
+
+	if binCmixType.NumMethod() != cmixType.NumMethod() {
+		t.Errorf("WASM Cmix object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binCmixType.NumMethod(), cmixType.NumMethod())
+	}
+
+	for i := 0; i < binCmixType.NumMethod(); i++ {
+		method := binCmixType.Method(i)
+
+		if _, exists := cmixType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/connect_test.go b/wasm/connect_test.go
index f9cba409..c2acb98a 100644
--- a/wasm/connect_test.go
+++ b/wasm/connect_test.go
@@ -32,3 +32,23 @@ func Test_newConnectJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that Connection has all the methods that [bindings.Connection] has.
+func Test_ConnectionMethods(t *testing.T) {
+	connType := reflect.TypeOf(&Connection{})
+	binConnType := reflect.TypeOf(&bindings.Connection{})
+
+	if binConnType.NumMethod() != connType.NumMethod() {
+		t.Errorf("WASM Connection object does not have all methods from "+
+			"bindings.\nexpected: %d\nreceived: %d",
+			binConnType.NumMethod(), connType.NumMethod())
+	}
+
+	for i := 0; i < binConnType.NumMethod(); i++ {
+		method := binConnType.Method(i)
+
+		if _, exists := connType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/e2e_test.go b/wasm/e2e_test.go
index 107086be..d4b55d21 100644
--- a/wasm/e2e_test.go
+++ b/wasm/e2e_test.go
@@ -34,3 +34,23 @@ func Test_newE2eJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that E2e has all the methods that [bindings.E2e] has.
+func Test_E2eMethods(t *testing.T) {
+	e2eType := reflect.TypeOf(&E2e{})
+	binE2eType := reflect.TypeOf(&bindings.E2e{})
+
+	if binE2eType.NumMethod() != e2eType.NumMethod() {
+		t.Errorf("WASM E2e object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binE2eType.NumMethod(), e2eType.NumMethod())
+	}
+
+	for i := 0; i < binE2eType.NumMethod(); i++ {
+		method := binE2eType.Method(i)
+
+		if _, exists := e2eType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/fileTransfer_test.go b/wasm/fileTransfer_test.go
index bbdf8d98..b339903f 100644
--- a/wasm/fileTransfer_test.go
+++ b/wasm/fileTransfer_test.go
@@ -33,6 +33,26 @@ func Test_newFileTransferJS(t *testing.T) {
 	}
 }
 
+// Tests that FileTransfer has all the methods that [bindings.FileTransfer] has.
+func Test_FileTransferMethods(t *testing.T) {
+	ftType := reflect.TypeOf(&FileTransfer{})
+	binFtType := reflect.TypeOf(&bindings.FileTransfer{})
+
+	if binFtType.NumMethod() != ftType.NumMethod() {
+		t.Errorf("WASM FileTransfer object does not have all methods from "+
+			"bindings.\nexpected: %d\nreceived: %d",
+			binFtType.NumMethod(), ftType.NumMethod())
+	}
+
+	for i := 0; i < binFtType.NumMethod(); i++ {
+		method := binFtType.Method(i)
+
+		if _, exists := ftType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
+
 // Tests that the map representing FilePartTracker returned by
 // newFilePartTrackerJS contains all of the methods on FilePartTracker.
 func Test_newFilePartTrackerJS(t *testing.T) {
@@ -52,3 +72,24 @@ func Test_newFilePartTrackerJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that FilePartTracker has all the methods that
+// [bindings.FilePartTracker] has.
+func Test_FilePartTrackerMethods(t *testing.T) {
+	fptType := reflect.TypeOf(&FilePartTracker{})
+	binFptType := reflect.TypeOf(&bindings.FilePartTracker{})
+
+	if binFptType.NumMethod() != fptType.NumMethod() {
+		t.Errorf("WASM FilePartTracker object does not have all methods from "+
+			"bindings.\nexpected: %d\nreceived: %d",
+			binFptType.NumMethod(), fptType.NumMethod())
+	}
+
+	for i := 0; i < binFptType.NumMethod(); i++ {
+		method := binFptType.Method(i)
+
+		if _, exists := fptType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/follow.go b/wasm/follow.go
index 8da6a4d7..a21912fa 100644
--- a/wasm/follow.go
+++ b/wasm/follow.go
@@ -191,8 +191,32 @@ func (ce *clientError) Report(source, message, trace string) {
 //
 // Parameters:
 //  - args[0] - Javascript object that has functions that implement the
-//    [bindings.ClientError] interface
+//    [bindings.ClientError] interface.
 func (c *Cmix) RegisterClientErrorCallback(_ js.Value, args []js.Value) interface{} {
 	c.api.RegisterClientErrorCallback(&clientError{utils.WrapCB(args[0], "Report")})
 	return nil
 }
+
+// trackServicesCallback adheres to the [bindings.TrackServicesCallback]
+// interface.
+type trackServicesCallback struct {
+	callback func(args ...interface{}) js.Value
+}
+
+func (tsc *trackServicesCallback) Callback(marshalData []byte, err error) {
+	tsc.callback(utils.CopyBytesToJS(marshalData), utils.JsTrace(err))
+}
+
+// TrackServices will return, via a callback, the list of services that the
+// backend keeps track of, which is formally referred to as a
+// [message.ServiceList]. This may be passed into other bindings call that may
+// need context on the available services for this client.
+//
+// Parameters:
+//  - args[0] - Javascript object that has functions that implement the
+//    [bindings.TrackServicesCallback] interface.
+func (c *Cmix) TrackServices(_ js.Value, args []js.Value) interface{} {
+	c.api.TrackServices(
+		&trackServicesCallback{utils.WrapCB(args[0], "Callback")})
+	return nil
+}
diff --git a/wasm/group_test.go b/wasm/group_test.go
index cc64e5f8..1350fc4a 100644
--- a/wasm/group_test.go
+++ b/wasm/group_test.go
@@ -35,22 +35,62 @@ func Test_newGroupChatJS(t *testing.T) {
 	}
 }
 
+// Tests that GroupChat has all the methods that [bindings.GroupChat] has.
+func Test_GroupChatMethods(t *testing.T) {
+	gcType := reflect.TypeOf(&GroupChat{})
+	binGcType := reflect.TypeOf(&bindings.GroupChat{})
+
+	if binGcType.NumMethod() != gcType.NumMethod() {
+		t.Errorf("WASM GroupChat object does not have all methods from "+
+			"bindings.\nexpected: %d\nreceived: %d",
+			binGcType.NumMethod(), gcType.NumMethod())
+	}
+
+	for i := 0; i < binGcType.NumMethod(); i++ {
+		method := binGcType.Method(i)
+
+		if _, exists := gcType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
+
 // Tests that the map representing Group returned by newGroupJS contains all of
 // the methods on Group.
 func Test_newGroupJS(t *testing.T) {
-	gType := reflect.TypeOf(&Group{})
+	grpType := reflect.TypeOf(&Group{})
 
 	g := newGroupJS(&bindings.Group{})
-	if len(g) != gType.NumMethod() {
+	if len(g) != grpType.NumMethod() {
 		t.Errorf("Group JS object does not have all methods."+
-			"\nexpected: %d\nreceived: %d", gType.NumMethod(), len(g))
+			"\nexpected: %d\nreceived: %d", grpType.NumMethod(), len(g))
 	}
 
-	for i := 0; i < gType.NumMethod(); i++ {
-		method := gType.Method(i)
+	for i := 0; i < grpType.NumMethod(); i++ {
+		method := grpType.Method(i)
 
 		if _, exists := g[method.Name]; !exists {
 			t.Errorf("Method %s does not exist.", method.Name)
 		}
 	}
 }
+
+// Tests that Group has all the methods that [bindings.Group] has.
+func Test_GroupMethods(t *testing.T) {
+	grpType := reflect.TypeOf(&Group{})
+	binGrpType := reflect.TypeOf(&bindings.Group{})
+
+	if binGrpType.NumMethod() != grpType.NumMethod() {
+		t.Errorf("WASM Group object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binGrpType.NumMethod(), grpType.NumMethod())
+	}
+
+	for i := 0; i < binGrpType.NumMethod(); i++ {
+		method := binGrpType.Method(i)
+
+		if _, exists := grpType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
diff --git a/wasm/single_test.go b/wasm/single_test.go
index 48017c5d..d1276075 100644
--- a/wasm/single_test.go
+++ b/wasm/single_test.go
@@ -10,6 +10,7 @@
 package wasm
 
 import (
+	"gitlab.com/elixxir/client/bindings"
 	"reflect"
 	"testing"
 )
@@ -34,6 +35,26 @@ func Test_newStopperJS(t *testing.T) {
 	}
 }
 
+// Tests that Stopper has all the methods that [bindings.Stopper] has.
+func Test_StopperMethods(t *testing.T) {
+	stopperType := reflect.TypeOf(&Stopper{})
+	binStopperType := reflect.TypeOf(bindings.Stopper(&stopper{}))
+
+	if binStopperType.NumMethod() != stopperType.NumMethod() {
+		t.Errorf("WASM Stopper object does not have all methods from bindings."+
+			"\nexpected: %d\nreceived: %d",
+			binStopperType.NumMethod(), stopperType.NumMethod())
+	}
+
+	for i := 0; i < binStopperType.NumMethod(); i++ {
+		method := binStopperType.Method(i)
+
+		if _, exists := stopperType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
+
 type stopper struct{}
 
 func (s *stopper) Stop() {}
diff --git a/wasm/ud_test.go b/wasm/ud_test.go
index 37761fa9..40ae06bc 100644
--- a/wasm/ud_test.go
+++ b/wasm/ud_test.go
@@ -34,3 +34,24 @@ func Test_newUserDiscoveryJS(t *testing.T) {
 		}
 	}
 }
+
+// Tests that UserDiscovery has all the methods that [bindings.UserDiscovery]
+// has.
+func Test_UserDiscoveryMethods(t *testing.T) {
+	udType := reflect.TypeOf(&UserDiscovery{})
+	binUdType := reflect.TypeOf(&bindings.UserDiscovery{})
+
+	if binUdType.NumMethod() != udType.NumMethod() {
+		t.Errorf("WASM UserDiscovery object does not have all methods from "+
+			"bindings.\nexpected: %d\nreceived: %d",
+			binUdType.NumMethod(), udType.NumMethod())
+	}
+
+	for i := 0; i < binUdType.NumMethod(); i++ {
+		method := binUdType.Method(i)
+
+		if _, exists := udType.MethodByName(method.Name); !exists {
+			t.Errorf("Method %s does not exist.", method.Name)
+		}
+	}
+}
-- 
GitLab