jquerytestingmockingscala.jsutest

Mock Scala.js classes


I'm trying to test React component written in Scala.js, which fetches list of categories from the server. I was able to provide alternative jQuery instance to the component, but jQuery mock itself cannot be compiled. Here is mock's code:

import org.scalajs.jquery.{JQueryXHR, JQueryStatic}

import scala.scalajs.js
import utest._

class jQueryMock extends JQueryStatic {

  var awaitedRequests = Map.empty[String, PartialFunction[js.Any, js.Any]]

  def whenGet(url: String)(response: PartialFunction[js.Any, js.Any]): Unit = {
    awaitedRequests += (url -> response)
  }

  override def get(url: String, data: js.Any, success: js.Any, dataType: js.Any): JQueryXHR = {
    awaitedRequests.get(url) match {
      case Some(response) =>
        if(response.isDefinedAt(data))
          success.asInstanceOf[(js.Any) => Unit](response(data))
        else
          assert(false)
      case None => assert(false)
    }
    new JQueryXHR {}
  }
}

There are two problems in this code according to Scala.js compiler:

Is there any other way to mock any native class in Scala.js (or in fact any other way to test backend queries)?

Edit

If I throw out extends JQueryStatic and new JQueryXHR {} and change return type of def get, the class compiles fine. This way I could write jQuery wrapper handling AJAX stuff, which I will be able to mock. This will work, but seems to be an awful lot of trouble. Is there any other way to do this?


Solution

  • I've created tests using my facade and it's mock:

    Facade

    class Http {
      def get(url: String)(success: (js.UndefOr[js.Any]) => Unit): Unit =
        jQuery.getJSON(url, js.undefined, success)
    }
    

    Mock

    class HttpMock extends Http {
    
      var awaitedRequests = Map.empty[String, js.Any]
    
      def whenGet(url: String, response: js.Any): Unit = {
        awaitedRequests += (url -> response)
      }
    
      def verifyNoOutstandingRequests() =
        assert(awaitedRequests.isEmpty)
    
      override def get(url: String)(success: (js.UndefOr[js.Any]) => Unit): Unit = {
        awaitedRequests.get(url) match {
          case Some(response) =>
              success(response)
              awaitedRequests -= url
          case None => assert(false)
        }
      }
    }