How to handle Action which returns Accumultor[ByteString,Result] in unit test - playframework-2.6

My Action returns Accumulator[ByteString,Result]. I want to unit test the Accumulator. How can I test it? I am trying to use contentAsJson which accepts a variable of type Accumulator[ByteString,Result] but the Right side of Either is not giving me the content. The following is the test case.
"newQuestion" should {
"should return error if tag information in the question isn't in correct format" in {
val testEnv = new QuestionsControllerSpecTestEnv(components=components)
val body =
s"""
|{
| "practice-question":{
| "description": "some description",
| "hints": ["hint1","hint2"],
| "image": ["image1 data","image2 data"],
| "success-test": "success test",
| "fail-test": "fail test",
| "tags": ["tag1-in-incorrect-format","tag2IsAlsoWrong"],
| "title":"some title",
| "answer": "some answer",
| "references":["ref1","ref2"]
| }
|}
""".stripMargin
val jsonBody = Json.parse(body)
val request = new FakeRequest(FakeRequest("POST","ws/questions/new-question")).withAuthenticator(testEnv.testEnv.loginInfo)(testEnv.testEnv.fakeEnv).withBody(AnyContentAsJson(jsonBody))
val response = testEnv.questionsController.newQuestion(request)
val responseBody = contentAsJson(response)//(Timeout(Duration(5000,"millis")),testEnv.testEnv.mat)
println(s"received response body ${responseBody}")
val result = (responseBody \ "result").get.as[String]
val additionalInfo = (responseBody \ "additional-info").get.as[String]
result mustBe "error"
additionalInfo mustBe components.messagesApi("error.invalidTagStructure")(components.langs.availables(0))
}
}
The controller is receiving a body of type Right(AnyContentAsRaw(RawBuffer(inMemory=0, backedByTemporaryFile=null)))
Why am I not seeing the JSON in the body?

I need to call run method of the Accumulator to start the stream which will pass data to the Accumulator.
run method has 3 variants.
abstract def run(elem: E)(implicit materializer: Materializer): Future[A]
Run this accumulator by feeding a single element into it.
abstract def run()(implicit materializer: Materializer): Future[A]
Run this accumulator by feeding nothing into it.
abstract def run(source: Source[E, _])(implicit materializer: Materializer): Future[A]
Run this accumulator by feeding in the given source.
The E seems to be the data type of stream. In my case, Accumulator[-E,+A] has E equal to ByteStream. So I converted the string body into Bytestream and pass it to run. run returns Future[Result] which could then be processed usingcontentAsJsonmethod ofHelpers` class
val body =
s"""
|{
| "practice-question":{
| "description": "some description",
| "hints": ["hint1","hint2"],
| "image": ["image1 data","image2 data","image3 data"],
| "success-test": "success test",
| "fail-test": "fail test",
| "tags": ["${testEnv.tag}","${testEnv.tag}"],
| "title":"some title",
| "answer": "some answer",
| "references":["ref1","ref2"]
| }
|}
""".stripMargin
val jsonBody = Json.parse(body)
println("jsBody is "+jsonBody)
...
val request = new FakeRequest(FakeRequest("POST","ws/questions/new-question")).withAuthenticator(testEnv.testEnv.loginInfo)(testEnv.testEnv.fakeEnv).withHeaders(CONTENT_TYPE->"application/json").withBody(AnyContentAsJson(jsonBody))
val response = testEnv.questionsController.newQuestion(request)
val accumulatorResult = response.run(ByteString(body)) //use run to start the Accumulator
val responseBody = contentAsJson(accumulatorResult)//(Timeout(Duration(5000,"millis")),testEnv.testEnv.mat)
..

Related

F# Bolero how to set the code apart to make the project structure clear?

I'm new to F# and Bolero. and after initialize the project as the docs shows, I find that sample application demonstrates 3 types of web applications but main codes is in one file called Main.fs .
here is part codes:
type Message =
| SetPage of Page
| Increment
| Decrement
| SetCounter of int
| GetBooks
| GotBooks of Book[]
| SetUsername of string
| SetPassword of string
| GetSignedInAs
| RecvSignedInAs of option<string>
| SendSignIn
| RecvSignIn of option<string>
| SendSignOut
| RecvSignOut
| Error of exn
| ClearError
let update remote message model =
let onSignIn = function
| Some _ -> Cmd.ofMsg GetBooks
| None -> Cmd.none
match message with
| SetPage page ->
{ model with page = page }, Cmd.none
| Increment ->
{ model with counter = model.counter + 1 }, Cmd.none
| Decrement ->
{ model with counter = model.counter - 1 }, Cmd.none
| SetCounter value ->
{ model with counter = value }, Cmd.none
| GetBooks ->
let cmd = Cmd.OfAsync.either remote.getBooks () GotBooks Error
{ model with books = None }, cmd
| GotBooks books ->
{ model with books = Some books }, Cmd.none
| SetUsername s ->
{ model with username = s }, Cmd.none
| SetPassword s ->
{ model with password = s }, Cmd.none
| GetSignedInAs ->
model, Cmd.OfAuthorized.either remote.getUsername () RecvSignedInAs Error
| RecvSignedInAs username ->
{ model with signedInAs = username }, onSignIn username
| SendSignIn ->
model, Cmd.OfAsync.either remote.signIn (model.username, model.password) RecvSignIn Error
| RecvSignIn username ->
{ model with signedInAs = username; signInFailed = Option.isNone username }, onSignIn username
| SendSignOut ->
model, Cmd.OfAsync.either remote.signOut () (fun () -> RecvSignOut) Error
| RecvSignOut ->
{ model with signedInAs = None; signInFailed = false }, Cmd.none
| Error RemoteUnauthorizedException ->
{ model with error = Some "You have been logged out."; signedInAs = None }, Cmd.none
| Error exn ->
{ model with error = Some exn.Message }, Cmd.none
| ClearError ->
{ model with error = None }, Cmd.none
As you can see, the code is too long to manage. if I add more functionality I can barely imagine what the file will be like.
so how can I split the code into different files ?
The most basic thing you could do is to split your Message type into multiple separate types and have one corresponding to different aspects of the logic. For example:
type CounterMessage =
| Increment
| Decrement
| SetCounter of int
type BooksMessage =
| GetBooks
| GotBooks of Book[]
type Message =
| SetPage of Page
| CounterMessage of CounterMessage
| BooksMessage of BooksMessage
Then you can similarly split your update function - and move each of the message-specific functions to a separate file:
let updateCounter remote message model =
match message with
| Increment ->
{ model with counter = model.counter + 1 }, Cmd.none
| Decrement ->
{ model with counter = model.counter - 1 }, Cmd.none
| SetCounter value ->
{ model with counter = value }, Cmd.none
let update remote message model =
match message with
| SetPage page ->
{ model with page = page }, Cmd.none
| CounterMessage msg ->
updateCounter remote message model
// (...)
This is something using just basic F# langauge mechanisms. Perhaps Bolero has some more sophisticated methods for structuring projects, but this is simple option will always work. The disadvantage is that you need to handle the "forwarding" of the messages yourself (and this is something that a more sophisticated option may alleviate) - but I think that for a moderately sized project, it is not such a bad things (and it helps making things explicit and clear).

How to encapsulate logic within children like component frameworks?

I'm trying to understand how to create reusable components using the Elmish architecture within F# Bolero by WebSharper (e.g. a reusable validated form input). From all of the examples I've seen, the top level Parent must handle all messages/updates and logic, while children are simply for views. I'm wondering if there's a way around this, whether by having a child handle its own state + messages, and propagating certain messages to the parent (which I've attempted in code below), or if there's another design to handle this.
In my specific case, I'm trying to create a form input component for a users name that validates neither field is empty. I don't like the idea of having a parent handle updating the individual fields FirstName and LastName, it should only care about picking up the Submit message. Handling every message a child produces would results in a ton of boilerplate if you use the child more than once
Note: The code I've provided does not compile as I'm struggling to understand how to implement my intended design
open Elmish
open Bolero
open Bolero.Html
module NameInput =
type Model = { FirstName : string; LastName : string }
type Message =
| ChangeFirstName of string
| ChangeLastName of string
| Submit of Model
let update model msg =
match msg with
| ChangeFirstName s ->
{ model with FirstName = s}, Cmd.none
| ChangeLastName s ->
{ model with LastName = s}, Cmd.none
| Submit m ->
m, Cmd.ofMsg (Submit m)
type Component() =
inherit ElmishComponent<Message, Model>()
let invalidField s = s <> ""
override this.View model dispatch =
let fnClass = if (invalidField model.FirstName) then "invalid" else "valid"
let lnClass = if (invalidField model.LastName) then "invalid" else "valid"
div [] [
label [] [ text "First Name: " ]
input [
attr.``class`` fnClass
on.change (fun e -> update model (ChangeFirstName (unbox e.Value)))
]
label [] [ text "Last Name: " ]
input [
attr.``class`` lnClass
on.change (fun e -> update model (ChangeLastName (unbox e.Value)))
]
button [ on.click (fun _ -> update model (Submit model)) ] [ text "Submit" ]
]
type Message =
| NameSubmitted of NameInput.Message.Submit
type Model = { UserName : NameInput.Model }
let initModel = { UserName = { FirstName = ""; LastName = "" } }
let update msg model =
match msg with
| NameSubmitted name ->
// Greet the user
{ model with UserName = name }, Cmd.none
let view model dispatch =
concat [
ecomp<NameInput.Component,_,_>
model.Username dispatch
]
type MyApp() =
inherit ProgramComponent<Model, Message>()
override this.Program =
Program.mkProgram (fun _ -> initModel, Cmd.none) update view
Thank you #rmunn and #hvester for the references, it helped me get a better understanding of Elmish and was able to come up with a solution. As a reference for anyone else who may stumble across this, here is the solution. InternalMessage does not need to private, it just hides those cases from the main program's update function so one can easily see which messages they need to handle. If it is public though, compiler will give an error if you try to match on an InternalMessage case without first unwrapping the Message into an InternalMessage (so the programmer still easily knows which messages are internal)
module NameInput =
type Model = { FirstName : string; LastName : string }
type private InternalMessage =
| ChangeFirstName of string
| ChangeLastName of string
type Message =
| Internal of InternalMessage
| Submit of Model
let update msg model =
match msg with
| ChangeFirstName s ->
{ model with FirstName = s }
| ChangeLastName s ->
{ model with LastName = s }
type Component() =
inherit ElmishComponent<Model, Message>()
let invalidField s = s <> ""
override this.View model dispatch =
let fnClass = if (invalidField model.FirstName) then "invalid" else "valid"
let lnClass = if (invalidField model.LastName) then "invalid" else "valid"
div [] [
label [] [ text "First Name: " ]
input [
attr.``class`` fnClass
on.change (fun e -> dispatch << Internal << ChangeFirstName <| unbox e.Value)
]
label [] [ text "Last Name: " ]
input [
attr.``class`` lnClass
on.change (fun e -> dispatch << Internal << ChangeLastName <| unbox e.Value)
]
button [ on.click (fun _ -> dispatch <| Submit model) ] [ text "Submit" ]
]
type Model = { Name : NameInput.Model }
let initModel = { Name = { FirstName = ""; LastName = "" } }
type Message =
| NameInput of NameInput.Message
let update message model =
match message with
| NameInput ni ->
match ni with
| NameInput.Internal i ->
{ model with Name = model.Name |> NameInput.update i}
| NameInput.Submit n ->
{ model with Name = n }

Unable to embed document fragment into a WebSharper page trough a `Var<Doc>`

I am quite new to using WebSharper and I might be doing things the wrong way.
My goal is to be able to update the contents of my page as a result of user actions by updating a Var<Doc> variable representing a portion of the page to be updated. I'd be happy to know if I could update a Var<Doc> from server-side code and have it reflect in the user's browser.
Below is a quick example:
let TestPage ctx =
let clientPart = Var.Create <| Doc.Empty
clientPart .Value <- div [] [ text "This content is dynamically inserted" ]
Templating.Main ctx EndPoint.Home "Home" [
h1 [] [text "Below is a dynamically inserted content:"]
div [] [ client <# clientPart .View |> Doc.EmbedView #> ]
]
The error I receive is:
System.Exception: Error during RPC JSON conversion ---> System.Exception: Failed to look up translated field name for write' in type WebSharper.UI.Elt with fields: docNode, elt, rvUpdates, updates
The WebSharper 4 documentation regarding Views also states:
It will only be run while the resulting View is included in the document using one of these methods:
Doc.BindView
Doc.EmbedView
textView
and etc.
A similar error is produced if I try this instead:
type SomeTemplate = Template<"SomeTemplate.html">
clientDoc.Value <- SomeTemplate().Doc()
In the above code, Templating.Main is the same as in the default WebSharper project:
module Templating =
...
let Main ctx action (title: string) (body: Doc list) =
let t = MainTemplate().Title(title).MenuBar(MenuBar ctx action).With("Body", body)
let doc : Doc = t.Doc()
doc |> Content.Page
Here is an example calling an RPC on the server side and storing it into a client Var<>:
module ServerFunctions =
let mutable ServerState = ("Zero", 0)
let [< Rpc >] addToState n = async {
let state, counter = ServerState
let newCounter = counter + n
let newState = if newCounter = 0 then "Zero" else "NonZero"
ServerState <- newState, newCounter
return newState
}
[< JavaScript >]
module ClientFunctions =
open WebSharper
open WebSharper.UI
open WebSharper.UI.Html
open ServerFunctions
let zeroState = Var.Create "do not know"
let clientDoc() =
div [] [
h1 [] [ text "State of zero on server:" ]
h2 [] [ text zeroState.V ]
Doc.Button "increment" [] (fun () -> async { let! state = addToState 1
zeroState.Set state
} |> Async.Start)
Doc.Button "decrement" [] (fun () -> async { let! state = addToState -1
zeroState.Set state
} |> Async.Start)
]
module Server =
open global.Owin
open Microsoft.Owin.Hosting
open Microsoft.Owin.StaticFiles
open Microsoft.Owin.FileSystems
open WebSharper.Owin
open WebSharper.UI.Server
open WebSharper.UI.Html
type EndPointServer =
| [< EndPoint "/" >] Hello
| About
let url = "http://localhost:9006/"
let rootdir = #"..\website"
let site() = WebSharper.Application.MultiPage(fun context (s:EndPointServer) ->
printfn "Serving page: %A" s
Content.Page(
Title= ( sprintf "Test %A" s)
, Body = [ h1 [] [ text <| sprintf "%A" s ]
Html.client <# ClientFunctions.clientDoc() #> ])
)

dispatch method in view for parent child composition

I am trying to understand the way fable is supposed to work with parent child composition. Things are quite easy when it comes to update method, init, and the definition of commands. But the view method and its dispatch method are tricky to find out
In my code, the child is:
module DeploymentView
type DeploymentTypeView =
| DeployContainerView
type Model = {
CurrentView : DeploymentTypeView option
}
type Msg =
| ShowDeployContainer
let init () : Model =
let initialModel = {
CurrentView = None
}
initialModel
let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
match msg with
| ShowDeployContainer ->
let nextModel = {
currentModel with CurrentView = Some DeployContainerView
}
nextModel, Cmd.none
| _ -> currentModel, Cmd.none
let view (model : Model) (dispatch : Msg -> unit) =
[
Content.content [ Content.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Left) ] ]
[
Heading.h3 [] [ str ("Deployments: ") ]
]
Columns.columns []
[
Column.column [] [ button "deploy container" (fun _ -> dispatch ShowDeployContainer) ]
]
]
And following this documentation about parent child processing I have define a parent like this one:
module Client
type PortalView =
| DeploymentView of DeploymentView.Model
| ProductAdministrationView
type Model = {
CurrentPortal : PortalView option
}
// The Msg type defines what events/actions can occur while the application is running
// the state of the application changes *only* in reaction to these events
type Msg =
| ShowDeployment
| ShowAdministration
| DeployContainerView of DeploymentView.Msg
// defines the initial state and initial command (= side-effect) of the application
let init () : Model * Cmd<Msg> =
let initialModel = {
CurrentPortal = None
}
initialModel, Cmd.none
let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
match msg with
| ShowDeployment ->
let nextModel = {
currentModel with CurrentPortal = Some <| DeploymentView(DeploymentView.init())
}
nextModel, Cmd.none
| ShowAdministration ->
let nextModel = {
currentModel with CurrentPortal = Some ProductAdministrationView
}
nextModel, Cmd.none
| DeployContainerView msg' ->
let res, cmd =
match currentModel.CurrentPortal with
| Some(DeploymentView(m)) -> DeploymentView.update msg' m
| _ -> DeploymentView.init(), Cmd.none
{ currentModel with CurrentPortal = Some(DeploymentView(res)) }, Cmd.map DeployContainerView cmd
So far so good, my issue comes when it goes to the rendering of the view itself.
The client view uses a function as follows:
let view (model : Model) (dispatch : Msg -> unit)
where Msg is of type DeploymentView.Msg whereas in the parent view I have access to a dispatch of type Client.Msg -> unit. how can I decompose the parent dispatch to map it to the child dispatch signature?
You can very easily create a dispatch function that conforms to what the child expects by using the >> operator:
DeploymentView.view deploymentViewModel (DeployContainerView >> dispatch)
which is equivalent to doing:
DeploymentView.view deploymentViewModel (fun msg -> msg |> DeployContainerView |> dispatch)
That is, it wraps the child's message in DeployContainerView, then passes that to dispatch.
On another note, it is a common and good convention to use a Msg suffix on constructors used to wrap child msg types. You may want to consider renaming DeployContainerView to DeploymentContainerMsg.

F# - Print match expression result

I think this will be simple but I've spent the past hour trying everything I can think of and researching online to no avail.
(I'm new to F#)
I have the following code which sends a HTTP Request, it then matches the result. If it doesn't match anything ( | _ ) I want to just print its string value to console. How would I go about doing this?
match Http.RequestString("http://foo.com/res.php",
httpMethod = "GET",
query = ["key", key; "action", "get"; "id", id]) with
| "CAPCHA_NOT_READY" -> printfn "Sleeping for 5"
Thread.Sleep(5000)
GetCaptchaRequest id
| _ -> printfn ???
The underscore character is used when you don't care about the value and won't be using it in subsequent code. You just need to give the variable a name. Try this:
| msg -> printfn "%s" msg
In this example, I've chosen msg as the variable name but it can be any valid variable name you choose.
Since all the branches of a match statement must return the same type, you will need more than just the printfn statement. In cases like this, where the external call could potentially fail, it is a common idiom to use the Option<'a> type to represent success or failure.
Not knowing the specifics of your API endpoint, consider this pseudocode:
let GetCaptchaRequest id : string option =
match Http.RequestString("http://foo.com/res.php",
httpMethod = "GET",
query = ["key", key; "action", "get"; "id", id]) with
| "CAPCHA_NOT_READY" -> printfn "Sleeping for 5"
Thread.Sleep(5000)
GetCaptchaRequest id
| "ERROR" -> printfn "Something went wrong!"
None
| result -> printfn "Successful result!"
Some (parseMyCaptchaResult result)

Resources