Skip to content
Permalink
Browse files

Update ScalaJS (#124)

* Update plugins

* Update ScalaCSS

* Add a test for AtTriggerInput component

* Disable Scoverage in ScalaJS for dynamic literal

* Replace MockServer by WireMock
  • Loading branch information...
A. Alonso Dominguez
A. Alonso Dominguez committed Nov 8, 2017
1 parent 2c7a6b0 commit 4c220ee1d81710e6fde1f10bd9cc36cd9ed887a9
@@ -55,7 +55,6 @@ lazy val commonJvmSettings = Seq(

lazy val commonJsSettings = Seq(
coverageEnabled := false,
coverageExcludedFiles := ".*",
scalaJSStage in Test := FastOptStage,
jsEnv in Test := PhantomJSEnv().value,
// batch mode decreases the amount of memory needed to compile scala.js code
@@ -16,28 +16,41 @@

package io.quckoo.client.http

import org.mockserver.integration.{ClientAndProxy, ClientAndServer}
import org.mockserver.socket.PortFactory
import java.net.ServerSocket
import java.util.concurrent.TimeUnit

import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
import org.scalatest.{BeforeAndAfterAll, Outcome, fixture}

import scala.util.control.NonFatal

/**
* Created by alonsodomin on 19/09/2016.
*/
trait MockServer extends fixture.FlatSpec with BeforeAndAfterAll {
type FixtureParam = ClientAndServer

private[this] var proxy: ClientAndProxy = _
trait WireMock extends fixture.FlatSpec with BeforeAndAfterAll {
type FixtureParam = WireMockServer

override protected def beforeAll(): Unit =
proxy = ClientAndProxy.startClientAndProxy(PortFactory.findFreePort())
private[this] def findFreePort(): Int = {
var port: Int = -1
try {
val socket = new ServerSocket(0)
port = socket.getLocalPort
socket.close()

override protected def afterAll(): Unit = proxy.stop()
// Give some time to allow the socket to be released
TimeUnit.MILLISECONDS.sleep(50)
} catch {
case NonFatal(ex) =>
throw new RuntimeException("Could not allocate a free port.", ex)
}
port
}

override protected def withFixture(test: OneArgTest): Outcome = {
val server =
ClientAndServer.startClientAndServer(PortFactory.findFreePort())
val server = new WireMockServer(options().port(findFreePort()))
try {
proxy.reset()
server.start()
withFixture(test.toNoArgTest(server))
} finally {
server.stop()
@@ -21,16 +21,11 @@ import akka.actor.ActorSystem
import io.circe.generic.auto._

import io.quckoo.{ArtifactId, JobId}
import io.quckoo.client.http.{HttpMethod, HttpRequest, MockServer}
import io.quckoo.client.http.{HttpMethod, HttpRequest, WireMock}
import io.quckoo.serialization.DataBuffer
import io.quckoo.serialization.json._

import org.mockserver.model.{
JsonBody,
HttpRequest => MockHttpRequest,
HttpResponse => MockHttpResponse
}
import org.mockserver.verify.VerificationTimes
import com.github.tomakehurst.wiremock.client.WireMock._

import org.scalatest.{Matchers, fixture}

@@ -40,7 +35,7 @@ import scala.concurrent.duration.Duration
/**
* Created by alonsodomin on 20/09/2016.
*/
class AkkaHttpBackendSpec extends fixture.FlatSpec with MockServer with Matchers {
class AkkaHttpBackendSpec extends fixture.FlatSpec with WireMock with Matchers {
implicit val actorSystem = ActorSystem("AkkaHttpBackendSpec")

override protected def afterAll(): Unit = {
@@ -49,28 +44,25 @@ class AkkaHttpBackendSpec extends fixture.FlatSpec with MockServer with Matchers
}

"on send" should "parse error codes correctly in any HTTP method" in { mockServer =>
val transport = new HttpAkkaBackend("localhost", mockServer.getPort)
val transport = new HttpAkkaBackend("localhost", mockServer.port)

for (method <- HttpMethod.values) {
val mockHttpRequest =
MockHttpRequest.request("/nowhere").withMethod(method.entryName)
val mockHttpResponse = MockHttpResponse.notFoundResponse()

mockServer.when(mockHttpRequest).respond(mockHttpResponse)
mockServer.stubFor(
request(method.entryName, anyUrl)
.willReturn(notFound)
)

val response = Await.result(
transport.send(HttpRequest(method, "/nowhere", Duration.Inf, Map.empty)),
Duration.Inf
)

response.statusCode shouldBe 404

mockServer.verify(mockHttpRequest, VerificationTimes.once())
}
}

it should "send JSON body request and parse the JSON output" in { mockServer =>
val transport = new HttpAkkaBackend("localhost", mockServer.getPort)
val transport = new HttpAkkaBackend("localhost", mockServer.port)

val input = ArtifactId("com.example", "example", "latest")
val output = JobId("fooId")
@@ -79,48 +71,37 @@ class AkkaHttpBackendSpec extends fixture.FlatSpec with MockServer with Matchers
.flatMap(in => DataBuffer(output).map(out => (in, out)))
.foreach {
case (in, out) =>
val requestBody = JsonBody.json(in.asString())
val responseBody = JsonBody.json(out.asString())

val mockHttpRequest = MockHttpRequest
.request("/path")
.withMethod("POST")
.withHeader("Content-Type", "application/json")
.withBody(requestBody)
val mockHttpResponse =
MockHttpResponse.response.withBody(responseBody)

mockServer.when(mockHttpRequest).respond(mockHttpResponse)
mockServer.stubFor(
post(urlEqualTo("/path"))
.withRequestBody(equalToJson(in.asString()))
.willReturn(okJson(out.asString()))
)

val headers = Map("Content-Type" -> "application/json")
val response = Await.result(
transport.send(HttpRequest(HttpMethod.Post, "/path", Duration.Inf, headers, in)),
Duration.Inf
)

mockServer.verify(mockHttpRequest, VerificationTimes.once())
response.entity.asString() shouldBe out.asString()
}
}

it should "send Authorization header" in { mockServer =>
val transport = new HttpAkkaBackend("localhost", mockServer.getPort)
val transport = new HttpAkkaBackend("localhost", mockServer.port)

val mockHttpRequest = MockHttpRequest
.request("/path")
.withMethod("POST")
.withHeader("Authorization", "foo")
val mockHttpResponse = MockHttpResponse.response.withBody("OK!")

mockServer.when(mockHttpRequest).respond(mockHttpResponse)
mockServer.stubFor(
post(urlEqualTo("/path"))
.withHeader("Authorization", equalTo("foo"))
.willReturn(ok("OK!"))
)

val headers = Map("Authorization" -> "foo")
val response = Await.result(
transport.send(HttpRequest(HttpMethod.Post, "/path", Duration.Inf, headers)),
Duration.Inf
)

mockServer.verify(mockHttpRequest, VerificationTimes.once())
response.entity.asString() shouldBe "OK!"
}

@@ -91,6 +91,7 @@ object CodeEditor {
private[this] def propagateUpdate: Callback =
$.state.flatMap(st => $.props.flatMap(_.onUpdate(st.value)))

// $COVERAGE-OFF$ https://github.com/scoverage/scalac-scoverage-plugin/issues/176
private[this] def jsOptions(props: Props): js.Dynamic =
js.Dynamic.literal(
"mode" -> props.options.mode.entryName,
@@ -103,6 +104,7 @@ object CodeEditor {
"autoRefresh" -> props.options.autoRefresh,
"readOnly" -> props.options.readOnly.asInstanceOf[js.Any]
)
// $COVERAGE-ON$

protected[CodeEditor] def initialize(props: Props, state: State): Callback =
$.getDOMNode
@@ -32,13 +32,19 @@ import scalacss.ScalaCssReact._
*/
object Modal {

case class Options(backdrop: Boolean = true, keyboard: Boolean = true, show: Boolean = true)

case class Props(header: Callback => VdomNode,
footer: Callback => VdomNode,
onClosed: Callback,
onShown: Option[Callback] = None,
options: Options = Options())
case class Options(
backdrop: Boolean = true,
keyboard: Boolean = true,
show: Boolean = true
)

case class Props(
header: Callback => VdomNode,
footer: Callback => VdomNode,
onClosed: Callback,
onShown: Option[Callback] = None,
options: Options = Options()
)

class Backend($ : BackendScope[Props, Unit]) {
private type RawModal = JQuery
@@ -70,15 +70,25 @@ object AtTriggerInput {
<.label(^.`class` := "col-sm-2 control-label", "Date"),
<.div(
^.`class` := "col-sm-10",
DateInput(state.date, onDateUpdate _, ^.readOnly := props.readOnly)
DateInput(
state.date,
onDateUpdate _,
^.id := "atTrigger_date",
^.readOnly := props.readOnly
)
)
),
<.div(
^.`class` := "form-group",
<.label(^.`class` := "col-sm-2 control-label", "Time"),
<.div(
^.`class` := "col-sm-10",
TimeInput(state.time, onTimeUpdate _, ^.readOnly := props.readOnly)
TimeInput(
state.time,
onTimeUpdate _,
^.id := "atTrigger_time",
^.readOnly := props.readOnly
)
)
)
)
@@ -0,0 +1,28 @@
/*
* Copyright 2015 A. Alonso Dominguez
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.quckoo.console.scheduler

import io.quckoo.console.test.ConsoleTestExports._

import org.scalajs.dom.html

class AtTriggerInputObserver($ : HtmlDomZipper) {

val dateInput = $("#atTrigger_date").domAs[html.Input]
val timeInput = $("#atTrigger_time").domAs[html.Input]

}
@@ -0,0 +1,82 @@
/*
* Copyright 2015 A. Alonso Dominguez
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.quckoo.console.scheduler

import java.time._

import io.quckoo.Trigger
import io.quckoo.console.test.ConsoleTestExports

import japgolly.scalajs.react.test.ReactTestUtils

import org.scalatest.FunSuite

object AtTriggerInputTest {
final val TestClock = Clock.fixed(Instant.EPOCH, ZoneOffset.UTC)
}

class AtTriggerInputTest extends FunSuite {
import ConsoleTestExports._
import AtTriggerInputTestDsl._
import AtTriggerInputTest._

val invariants: dsl.Invariants = {
var invars = dsl.emptyInvariant

invars &= dsl
.focus("Date")
.obsAndState(_.dateInput.value, _.date.map(_.toString).getOrElse(""))
.assert
.equal

invars &= dsl
.focus("Time")
.obsAndState(_.timeInput.value, _.time.map(_.toString).getOrElse(""))
.assert
.equal

invars
}

def runPlan(plan: dsl.Plan): Report[String] = {
val initialTrigger = Option.empty[Trigger.At]

ReactTestUtils.withRenderedIntoDocument(AtTriggerInput(initialTrigger, onUpdate)) { comp =>
def observe() = new AtTriggerInputObserver(comp.htmlDomZipper)

val test = plan
.addInvariants(invariants)
.withInitialState(State(None, None))
.test(Observer watch observe())

test.runU
}
}

test("input should update date and time") {
val newDate = LocalDate.now(TestClock).plusDays(25)
val newTime = LocalTime.now(TestClock).minusMinutes(15)

val plan = Plan.action(
noDate.assert(true) +> noTime.assert(true) +>
setDate(newDate) +> noDate.assert(false) +> noTime.assert(true) >>
setTime(newTime) +> noDate.assert(false) +> noTime.assert(false)
)

runPlan(plan).assert()
}
}

0 comments on commit 4c220ee

Please sign in to comment.
You can’t perform that action at this time.