Skip to content

Commit

Permalink
#1434 adding test for type ahead request at a view port level. Data i…
Browse files Browse the repository at this point in the history
…s loaded into table at initialisation
  • Loading branch information
naleeha authored and keikeicheung committed Aug 20, 2024
1 parent 58ac06a commit 4e7c25e
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void doDestroy() {

@Override
public String lifecycleId() {
return null;
return "PersonProvider";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.finos.vuu.core.module.typeahead

import com.typesafe.scalalogging.StrictLogging
import org.finos.vuu.core.table.{DataTable, TableContainer}
import org.finos.vuu.net.RequestContext
import org.finos.vuu.net.rpc.{DefaultRpcHandler, RpcMethodCallResult, RpcMethodSuccess, RpcParams}

class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends DefaultRpcHandler with StrictLogging {

this.registerRpc("getUniqueFieldValues", params => processGetUniqueFieldValuesRequest(params))
this.registerRpc("getUniqueFieldValuesStartingWith", params => processGetUniqueFieldValuesStartWithRequest(params))

def processGetUniqueFieldValuesRequest(params: RpcParams): RpcMethodCallResult = {
val values = getUniqueFieldValues(
params.namedParams("table").toString, //how to report error when expected param missing or fail to cast to right type
params.namedParams("module").toString,
params.namedParams("column").toString,
null //todo what to do about request context
)
RpcMethodSuccess(values)
}

def processGetUniqueFieldValuesStartWithRequest(params: RpcParams): RpcMethodCallResult = {
val values = getUniqueFieldValuesStartingWith(
params.namedParams("table").toString, //how to report error when expected param missing or fail to cast to right type
params.namedParams("module").toString,
params.namedParams("column").toString,
params.namedParams("starts").toString,
null //todo what to do about request context
)
RpcMethodSuccess(values) //how to control what viewport action to trigger?
}

def getUniqueFieldValues(tableName: String, moduleName: String, column: String, ctx: RequestContext): Array[String] = {
tableContainer.getTable(tableName) match {
case dataTable: DataTable =>
val columValueProvider = dataTable.getColumnValueProvider
columValueProvider.getUniqueValues(column)
case null =>
throw new Exception("Could not find table by name:" + tableName)
}
}

def getUniqueFieldValuesStartingWith(tableName: String, moduleName: String, column: String, starts: String, ctx: RequestContext): Array[String] = {
tableContainer.getTable(tableName) match {
case dataTable: DataTable =>
val columValueProvider = dataTable.getColumnValueProvider
columValueProvider.getUniqueValuesStartingWith(column, starts)
case null =>
throw new Exception("Could not find table by name:" + tableName)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.finos.vuu.net.rpc

import com.typesafe.scalalogging.StrictLogging
import org.finos.vuu.net.{Error, RequestContext, RpcCall, RpcResponse, ViewServerMessage, VsMsg}
import org.finos.vuu.viewport.{ViewPortAction, ViewPortRpcFailure, ViewPortRpcSuccess}
import org.finos.vuu.viewport.{DisplayResultAction, ViewPortAction, ViewPortRpcFailure, ViewPortRpcSuccess}

import java.util.concurrent.ConcurrentHashMap

Expand Down Expand Up @@ -30,7 +30,9 @@ class DefaultRpcHandler extends RpcHandler with StrictLogging {
override def processViewPortRpcCall(methodName: String, params: Array[Any], namedParams: Map[String, Any])(ctx: RequestContext): ViewPortAction = {
val result = processRpcMethodHandler(methodName, params, namedParams, ctx)
result match {
case RpcMethodSuccess(_) => ViewPortRpcSuccess()
case RpcMethodSuccess(result) =>
if(result == null) ViewPortRpcSuccess()
else DisplayResultAction(result)
case _: RpcMethodFailure => ViewPortRpcFailure(s"Exception occurred calling rpc $methodName")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ trait ViewPortAction {}
case class NoAction() extends ViewPortAction
case class OpenDialogViewPortAction(table: ViewPortTable, renderComponent: String = "grid") extends ViewPortAction
case class CloseDialogViewPortAction(vpId: String) extends ViewPortAction
case class ViewPortRpcSuccess() extends ViewPortAction {}
case class ViewPortRpcFailure(msg: String) extends ViewPortAction {}
case class DisplayResultAction(result: Any) extends ViewPortAction
case class ViewPortRpcSuccess() extends ViewPortAction
case class ViewPortRpcFailure(msg: String) extends ViewPortAction
case class ViewPortCreateSuccess(key:String) extends ViewPortAction

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(Array(
new Type(value = classOf[OpenDialogViewPortAction], name = "OPEN_DIALOG_ACTION"),
new Type(value = classOf[CloseDialogViewPortAction], name = "CLOSE_DIALOG_ACTION"),
new Type(value = classOf[NoAction], name = "NO_ACTION"),
new Type(value = classOf[DisplayResultAction], name = "DISPLAY_RESULT_ACTION"),
new Type(value = classOf[ViewPortEditSuccess], name = "VP_EDIT_SUCCESS"),
new Type(value = classOf[ViewPortEditFailure], name = "VP_EDIT_FAILURE"),
new Type(value = classOf[ViewPortRpcSuccess], name = "VP_RPC_SUCCESS"),
Expand Down
17 changes: 11 additions & 6 deletions vuu/src/test/scala/org/finos/vuu/net/TestModuleBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package org.finos.vuu.net
import org.finos.toolbox.lifecycle.LifecycleContainer
import org.finos.toolbox.time.Clock
import org.finos.vuu.api.{TableDef, ViewPortDef}
import org.finos.vuu.core.IVuuServer
import org.finos.vuu.core.module.{ModuleFactory, ModuleFactoryNode, TableDefContainer, ViewServerModule}
import org.finos.vuu.provider.MockProvider
import org.finos.vuu.core.table.{DataTable, TableContainer}
import org.finos.vuu.provider.{MockProvider, Provider, ProviderContainer}


object TestExtension {
Expand All @@ -17,20 +19,24 @@ object TestExtension {
)
}

def addTableForTest(tableDef: TableDef, viewPortDef: ViewPortDef)(implicit clock: Clock, lifecycle: LifecycleContainer): ModuleFactoryNode = {
def addTableForTest(
tableDef: TableDef,
ViewPortDefFactory: (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef,
providerFactory: (DataTable, IVuuServer) => Provider
)(implicit clock: Clock, lifecycle: LifecycleContainer): ModuleFactoryNode = {
moduleFactoryNode.addTable(
tableDef,
(table, _) => new MockProvider(table),
(_, _, _, _) => viewPortDef
providerFactory,
ViewPortDefFactory
)
}

}
}
class TestModuleBuilder(moduleName:String)(implicit clock: Clock, lifecycle: LifecycleContainer, tableDefContainer: TableDefContainer){


private var moduleFactory = ModuleFactory.withNamespace(moduleName)

def withTable(tableDef: TableDef, viewPortDef: ViewPortDef): TestModuleBuilder = {
moduleFactory = moduleFactory.addTable(
tableDef,
Expand All @@ -40,7 +46,6 @@ class TestModuleBuilder(moduleName:String)(implicit clock: Clock, lifecycle: Lif
this
}


def build(moduleName: String, tableDef: TableDef, viewPortDef: ViewPortDef)(implicit clock: Clock, lifecycle: LifecycleContainer, tableDefContainer: TableDefContainer): ViewServerModule =
ModuleFactory.withNamespace(moduleName)
.addTable(
Expand Down
39 changes: 39 additions & 0 deletions vuu/src/test/scala/org/finos/vuu/net/TestProvider.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.finos.vuu.net

import com.typesafe.scalalogging.StrictLogging
import org.finos.toolbox.time.Clock
import org.finos.vuu.core.table.{DataTable, RowWithData}
import org.finos.vuu.provider.Provider

class TestProvider(table: DataTable, fakeDataSource: FakeDataSource)(implicit clock: Clock) extends Provider with StrictLogging {

override def subscribe(key: String): Unit = {}

override def doStart(): Unit = {
logger.info(s"Test Provider for ${table.name}- Starting")
}

override def doStop(): Unit = {
logger.info(s"Test Provider for ${table.name}- Stopping")
}

override def doInitialize(): Unit = {
logger.info(s"Test Provider for ${table.name}- Initialising")
fakeDataSource.get()
.foreach(row => {
table.processUpdate(row._1, RowWithData(row._1, row._2), clock.now())
})
}

override def doDestroy(): Unit = {}

override val lifecycleId: String = s"TestProvider ${table.name}"
}
class FakeDataSource(rows: Map[String, Map[String, Any]]) {
type RowKey = String
type ColumnName = String

def get(): Map[RowKey, Map[ColumnName, Any]] = {
rows
}
}
60 changes: 54 additions & 6 deletions vuu/src/test/scala/org/finos/vuu/net/WebSocketApiTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package org.finos.vuu.net
import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl}
import org.finos.toolbox.lifecycle.LifecycleContainer
import org.finos.toolbox.time.{Clock, DefaultClock}
import org.finos.vuu.api.{ColumnBuilder, NoRpcHandler, TableDef, ViewPortDef}
import org.finos.vuu.api.{ColumnBuilder, TableDef, ViewPortDef}
import org.finos.vuu.core._
import org.finos.vuu.core.module.typeahead.ViewPortTypeAheadRpcHandler
import org.finos.vuu.core.module.{ModuleFactory, TableDefContainer, ViewServerModule}
import org.finos.vuu.core.table.{DataTable, TableContainer}
import org.finos.vuu.net.TestExtension.ModuleFactoryExtension
import org.finos.vuu.net.auth.AlwaysHappyAuthenticator
import org.finos.vuu.net.http.VuuHttp2ServerOptions
import org.finos.vuu.net.json.JsonVsSerializer
import org.finos.vuu.net.ws.WebSocketClient
import org.finos.vuu.viewport.ViewPortTable
import org.finos.vuu.provider.{Provider, ProviderContainer}
import org.finos.vuu.viewport.{DisplayResultAction, ViewPortRange, ViewPortTable}
import org.scalatest.featurespec.AnyFeatureSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.{BeforeAndAfterAll, GivenWhenThen}
Expand Down Expand Up @@ -42,7 +45,6 @@ class WebSocketApiTest extends AnyFeatureSpec with BeforeAndAfterAll with GivenW
def testStartUp(): TestVuuClient = {

implicit val metrics: MetricsProvider = new MetricsProviderImpl
implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map())

lifecycle.autoShutdownHook()

Expand Down Expand Up @@ -97,15 +99,24 @@ class WebSocketApiTest extends AnyFeatureSpec with BeforeAndAfterAll with GivenW
.addInt("Account")
.build()
)
val viewPortDef = ViewPortDef(

val viewPortDefFactory = (table: DataTable, provider: Provider, providerContainer: ProviderContainer, tableContainer: TableContainer) =>
ViewPortDef(
columns =
new ColumnBuilder()
.addString("Id")
.addInt("Account")
.build(),
service = NoRpcHandler
service = new ViewPortTypeAheadRpcHandler(tableContainer)
)

val dataSource = new FakeDataSource(Map(
"row1" -> Map("Id" -> "row1", "Name" -> "Becky Thatcher", "Account" -> 1235),
"row2" -> Map("Id" -> "row2", "Name" -> "Tom Sawyer", "Account" -> 45321),
"row3" -> Map("Id" -> "row3", "Name" -> "Huckleberry Finn", "Account" -> 89564),
))

val providerFactory = (table: DataTable, vuuServer: IVuuServer) => new TestProvider(table, dataSource)
val tableDef2 = TableDef(
name = "TableMetaDefaultVPTest",
keyField = "Id",
Expand All @@ -116,7 +127,7 @@ class WebSocketApiTest extends AnyFeatureSpec with BeforeAndAfterAll with GivenW
)

ModuleFactory.withNamespace("TEST")
.addTableForTest(tableDef, viewPortDef)
.addTableForTest(tableDef, viewPortDefFactory, providerFactory)
.addTableForTest(tableDef2)
.asModule()
}
Expand Down Expand Up @@ -167,6 +178,43 @@ class WebSocketApiTest extends AnyFeatureSpec with BeforeAndAfterAll with GivenW
assert(response.isDefined)
response.get.msg shouldEqual "No such table found with name null in module TEST. Table name and module should not be null"
}

Scenario("Type ahead rcp request for a column") {

Then("create viewport")
val createViewPortRequest = CreateViewPortRequest(ViewPortTable("TableMetaTest", "TEST"), ViewPortRange(1,100),columns = Array("Id", "Name", "Account"))
vuuClient.send(sessionId, tokenId, createViewPortRequest)
val viewPortCreateResponse = vuuClient.awaitForMsgWithBody[CreateViewPortSuccess]
val viewPortId = viewPortCreateResponse.get.viewPortId

//todo how to change the table data
//1. get access to provider and update directly - via adding new function to get provider from TableDefs in TableDefContainer?
//2. update the data source but have listener function to update the provider if data source change?
//3. only change when loading table for first time

val getTypeAheadRequest = ViewPortRpcCall(
viewPortId,
"getUniqueFieldValues",
params = Array(),
namedParams = Map(
"table" -> "TableMetaTest",
"module" -> "TEST",
"column" -> "Account"
))
vuuClient.send(sessionId, tokenId, getTypeAheadRequest)

Then("return top 10 values in that column")
val response = vuuClient.awaitForMsgWithBody[ViewPortRpcResponse]
assert(response.isDefined)

response.get.method shouldEqual "getUniqueFieldValues"

val action = response.get.action
action shouldBe a [DisplayResultAction]
val displayResultAction = action.asInstanceOf[DisplayResultAction]
displayResultAction.result shouldEqual List("1235", "45321", "89564")

}
}
}

0 comments on commit 4e7c25e

Please sign in to comment.