summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHaoyi Li <haoyi@haoyi-mbp.corp.dropbox.com>2014-11-26 00:45:31 -0800
committerHaoyi Li <haoyi@haoyi-mbp.corp.dropbox.com>2014-11-26 00:45:31 -0800
commit2c4b142503bd2d871e6818b5cab8c38627d9e4a0 (patch)
tree6ba33d2980a1a7a1286100202a695c6631bd240e /examples
downloadhands-on-scala-js-2c4b142503bd2d871e6818b5cab8c38627d9e4a0.tar.gz
hands-on-scala-js-2c4b142503bd2d871e6818b5cab8c38627d9e4a0.tar.bz2
hands-on-scala-js-2c4b142503bd2d871e6818b5cab8c38627d9e4a0.zip
Squashed 'examples/scala-js/' content from commit 47311ba
git-subtree-dir: examples/scala-js git-subtree-split: 47311ba693f949f204f27ea9475bb63425fbd4f3
Diffstat (limited to 'examples')
-rw-r--r--examples/helloworld/HelloWorld.scala86
-rw-r--r--examples/helloworld/helloworld-2.10-fastopt.html19
-rw-r--r--examples/helloworld/helloworld-2.10.html19
-rw-r--r--examples/helloworld/helloworld-2.11-fastopt.html19
-rw-r--r--examples/helloworld/helloworld-2.11.html19
-rw-r--r--examples/helloworld/startup.js8
-rw-r--r--examples/reversi/JSTypes.scala87
-rw-r--r--examples/reversi/Reversi.scala266
-rw-r--r--examples/reversi/reversi-2.10-fastopt.html30
-rw-r--r--examples/reversi/reversi-2.10.html30
-rw-r--r--examples/reversi/reversi-2.11-fastopt.html30
-rw-r--r--examples/reversi/reversi-2.11.html30
-rw-r--r--examples/testing/src/main/scala/ElementCreator.scala7
-rw-r--r--examples/testing/src/test/scala/CollectionTest.scala17
-rw-r--r--examples/testing/src/test/scala/ElementCreatorTest.scala24
-rw-r--r--examples/testing/testing-2.10-fastopt.html32
-rw-r--r--examples/testing/testing-2.10.html32
-rw-r--r--examples/testing/testing-2.11-fastopt.html32
-rw-r--r--examples/testing/testing-2.11.html32
19 files changed, 819 insertions, 0 deletions
diff --git a/examples/helloworld/HelloWorld.scala b/examples/helloworld/HelloWorld.scala
new file mode 100644
index 0000000..fd33060
--- /dev/null
+++ b/examples/helloworld/HelloWorld.scala
@@ -0,0 +1,86 @@
+/* Scala.js example code
+ * Public domain
+ * @author Sébastien Doeraene
+ */
+
+package helloworld
+
+import scala.scalajs.js
+import js.annotation.JSName
+
+object HelloWorld extends js.JSApp {
+ def main() {
+ if (!(!js.Dynamic.global.document) &&
+ !(!js.Dynamic.global.document.getElementById("playground"))) {
+ sayHelloFromDOM()
+ sayHelloFromTypedDOM()
+ sayHelloFromJQuery()
+ sayHelloFromTypedJQuery()
+ } else {
+ println("Hello world!")
+ }
+ }
+
+ def sayHelloFromDOM() {
+ val document = js.Dynamic.global.document
+ val playground = document.getElementById("playground")
+
+ val newP = document.createElement("p")
+ newP.innerHTML = "Hello world! <i>-- DOM</i>"
+ playground.appendChild(newP)
+ }
+
+ def sayHelloFromTypedDOM() {
+ val document = window.document
+ val playground = document.getElementById("playground")
+
+ val newP = document.createElement("p")
+ newP.innerHTML = "Hello world! <i>-- typed DOM</i>"
+ playground.appendChild(newP)
+ }
+
+ def sayHelloFromJQuery() {
+ // val $ is fine too, but not very recommended in Scala code
+ val jQuery = js.Dynamic.global.jQuery
+ val newP = jQuery("<p>").html("Hello world! <i>-- jQuery</i>")
+ newP.appendTo(jQuery("#playground"))
+ }
+
+ def sayHelloFromTypedJQuery() {
+ val jQuery = helloworld.JQuery
+ val newP = jQuery("<p>").html("Hello world! <i>-- typed jQuery</i>")
+ newP.appendTo(jQuery("#playground"))
+ }
+}
+
+object window extends js.GlobalScope {
+ val document: DOMDocument = js.native
+
+ def alert(msg: String): Unit = js.native
+}
+
+trait DOMDocument extends js.Object {
+ def getElementById(id: String): DOMElement = js.native
+ def createElement(tag: String): DOMElement = js.native
+}
+
+trait DOMElement extends js.Object {
+ var innerHTML: String = js.native
+
+ def appendChild(child: DOMElement): Unit = js.native
+}
+
+@JSName("jQuery")
+object JQuery extends js.Object {
+ def apply(selector: String): JQuery = js.native
+}
+
+trait JQuery extends js.Object {
+ def text(value: String): JQuery = js.native
+ def text(): String = js.native
+
+ def html(value: String): JQuery = js.native
+ def html(): String = js.native
+
+ def appendTo(parent: JQuery): JQuery = js.native
+}
diff --git a/examples/helloworld/helloworld-2.10-fastopt.html b/examples/helloworld/helloworld-2.10-fastopt.html
new file mode 100644
index 0000000..98b2705
--- /dev/null
+++ b/examples/helloworld/helloworld-2.10-fastopt.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Hello world - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/helloworld-fastopt.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/helloworld-launcher.js"></script>
+
+</body>
+</html>
diff --git a/examples/helloworld/helloworld-2.10.html b/examples/helloworld/helloworld-2.10.html
new file mode 100644
index 0000000..80b00b9
--- /dev/null
+++ b/examples/helloworld/helloworld-2.10.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Hello world - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/helloworld-opt.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/helloworld-launcher.js"></script>
+
+</body>
+</html>
diff --git a/examples/helloworld/helloworld-2.11-fastopt.html b/examples/helloworld/helloworld-2.11-fastopt.html
new file mode 100644
index 0000000..dbf5598
--- /dev/null
+++ b/examples/helloworld/helloworld-2.11-fastopt.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Hello world - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/helloworld-fastopt.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/helloworld-launcher.js"></script>
+
+</body>
+</html>
diff --git a/examples/helloworld/helloworld-2.11.html b/examples/helloworld/helloworld-2.11.html
new file mode 100644
index 0000000..9c9a3a1
--- /dev/null
+++ b/examples/helloworld/helloworld-2.11.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Hello world - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/helloworld-opt.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/helloworld-launcher.js"></script>
+
+</body>
+</html>
diff --git a/examples/helloworld/startup.js b/examples/helloworld/startup.js
new file mode 100644
index 0000000..f45e4cb
--- /dev/null
+++ b/examples/helloworld/startup.js
@@ -0,0 +1,8 @@
+/* Scala.js example code
+ * Public domain
+ * Author: Sébastien Doeraene
+ */
+
+$(function() {
+ ScalaJS.modules.helloworld_HelloWorld().main();
+});
diff --git a/examples/reversi/JSTypes.scala b/examples/reversi/JSTypes.scala
new file mode 100644
index 0000000..cc0e5a4
--- /dev/null
+++ b/examples/reversi/JSTypes.scala
@@ -0,0 +1,87 @@
+/* Scala.js example code
+ * Public domain
+ * @author Sébastien Doeraene
+ */
+
+package reversi
+
+import scala.scalajs.js
+
+trait Window extends js.Object {
+ val document: DOMDocument = js.native
+
+ def alert(msg: String): Unit = js.native
+}
+
+trait DOMDocument extends js.Object {
+ def getElementById(id: String): DOMElement = js.native
+ def createElement(tag: String): DOMElement = js.native
+}
+
+trait DOMElement extends js.Object {
+ var innerHTML: String = js.native
+
+ def appendChild(child: DOMElement): Unit = js.native
+}
+
+trait JQueryStatic extends js.Object {
+ def apply(arg: js.Any): JQuery = js.native
+ def apply(arg: js.Any, attributes: js.Any): JQuery = js.native
+}
+
+trait JQuery extends js.Object {
+ def get(index: Int): DOMElement = js.native
+
+ def text(value: String): JQuery = js.native
+ def text(): String = js.native
+
+ def html(value: String): JQuery = js.native
+ def html(): String = js.native
+
+ def prop(property: String): js.Any = js.native
+ def prop(property: String, value: js.Any): JQuery = js.native
+
+ def offset(): JQueryOffset = js.native
+
+ def appendTo(parent: JQuery): JQuery = js.native
+ def append(children: JQuery): JQuery = js.native
+
+ def addClass(classes: String): JQuery = js.native
+ def removeClass(classes: String): JQuery = js.native
+
+ def each[U](callback: js.Function2[Int, js.Dynamic, U]): JQuery = js.native
+
+ def click[U](handler: js.Function0[U]): JQuery = js.native
+ def click[U](handler: js.Function1[JQueryEvent, U]): JQuery = js.native
+}
+
+trait JQueryOffset extends js.Object {
+ val top: Double = js.native
+ val left: Double = js.native
+}
+
+trait JQueryEvent extends js.Object {
+ val pageX: Double = js.native
+ val pageY: Double = js.native
+}
+
+trait HTMLCanvasElement extends DOMElement {
+ def getContext(kind: String): js.Any = js.native // depends on the kind
+}
+
+trait CanvasRenderingContext2D extends js.Object {
+ val canvas: HTMLCanvasElement = js.native
+
+ var fillStyle: String = js.native
+ var lineWidth: Double = js.native
+
+ def fillRect(x: Double, y: Double, w: Double, h: Double): Unit = js.native
+ def strokeRect(x: Double, y: Double, w: Double, h: Double): Unit = js.native
+
+ def beginPath(): Unit = js.native
+ def fill(): Unit = js.native
+ def stroke(): Unit = js.native
+
+ def arc(x: Double, y: Double, radius: Double, startAngle: Double,
+ endAngle: Double, anticlockwise: Boolean): Unit = js.native
+}
diff --git a/examples/reversi/Reversi.scala b/examples/reversi/Reversi.scala
new file mode 100644
index 0000000..b4a34a4
--- /dev/null
+++ b/examples/reversi/Reversi.scala
@@ -0,0 +1,266 @@
+/* Scala.js example code
+ * Public domain
+ * @author Sébastien Doeraene
+ */
+
+package reversi
+
+import scala.annotation.tailrec
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExport
+
+sealed abstract class OptPlayer
+
+sealed abstract class Player extends OptPlayer {
+ val opponent: Player
+}
+
+case object NoPlayer extends OptPlayer
+
+case object White extends Player {
+ val opponent = Black
+}
+
+case object Black extends Player {
+ val opponent = White
+}
+
+@JSExport("Reversi")
+class Reversi(jQuery: JQueryStatic, playground: JQuery) {
+
+ // The Model -----------------------------------------------------------------
+
+ val BoardSize = 8 // size of a Reversi board
+
+ def inBounds(index: Int): Boolean = index >= 0 && index < BoardSize
+ def inBounds(x: Int, y: Int): Boolean = inBounds(x) && inBounds(y)
+
+ class Square(val x: Int, val y: Int) {
+ private var _owner: OptPlayer = NoPlayer
+
+ var onOwnerChange: (OptPlayer, OptPlayer) => Unit = (oldP, newP) => ()
+
+ def owner = _owner
+ def owner_=(value: OptPlayer) {
+ val previous = _owner
+ if (value != previous) {
+ _owner = value
+ onOwnerChange(previous, value)
+ }
+ }
+
+ override def toString() = "Square("+x+", "+y+", "+owner+")"
+ }
+
+ val board = Array.tabulate[Square](BoardSize, BoardSize)(new Square(_, _))
+ val allSquares = board.flatten
+ var currentPlayer: Player = White // Irrelevant, set again in startGame()
+
+ // The GUI -------------------------------------------------------------------
+
+ val resetButton = createResetButton()
+ val passButton = createPassButton()
+ val status = createStatus()
+ buildUI()
+
+ def createResetButton() = {
+ jQuery("<input>", js.Dynamic.literal(
+ `type` = "button", value = "Reset"
+ )).click(reset _)
+ }
+
+ def createPassButton() = {
+ jQuery("<input>", js.Dynamic.literal(
+ `type` = "button", value = "Pass"
+ )).click(pass _)
+ }
+
+ def createStatus() = {
+ jQuery("<span>")
+ }
+
+ def buildUI() {
+ // Some dimensions
+ val SquareSizePx = 48
+ val HalfSquareSizePx = SquareSizePx/2
+ val PawnRadiusPx = HalfSquareSizePx-4
+ val BoardSizePx = BoardSize*SquareSizePx + 3
+
+ // Creat the board canvas
+ val boardCanvas = jQuery(
+ "<canvas width='"+BoardSizePx+"' height='"+BoardSizePx+"'></canvas>")
+ val domCanvas = boardCanvas.get(0).asInstanceOf[HTMLCanvasElement]
+ val context = domCanvas.getContext("2d").asInstanceOf[CanvasRenderingContext2D]
+
+ playground.append(jQuery("<div>").append(boardCanvas))
+
+ /** Draw the specified square on the board canvas */
+ def drawSquare(square: Square) {
+ val x = square.x * SquareSizePx
+ val y = square.y * SquareSizePx
+
+ // Background
+ context.fillStyle = "green"
+ context.fillRect(x, y, SquareSizePx, SquareSizePx)
+
+ // Border
+ context.fillStyle = "black"
+ context.lineWidth = 3
+ context.strokeRect(x, y, SquareSizePx, SquareSizePx)
+
+ // Pawn
+ if (square.owner != NoPlayer) {
+ context.fillStyle = if (square.owner == White) "white" else "black"
+ context.beginPath()
+ context.arc(x+HalfSquareSizePx, y+HalfSquareSizePx, PawnRadiusPx,
+ 0, 2*Math.PI, true)
+ context.fill()
+ }
+ }
+
+ // Draw squares now, and everytime they change ownership
+ for (square <- allSquares) {
+ drawSquare(square)
+ square.onOwnerChange = { (prevOwner, newOwner) =>
+ drawSquare(square)
+ }
+ }
+
+ // Configure clicks on the board
+ boardCanvas.click { (event: JQueryEvent) =>
+ val offsetX = event.pageX - boardCanvas.offset().left
+ val offsetY = event.pageY - boardCanvas.offset().top
+ val x = offsetX.toInt / SquareSizePx
+ val y = offsetY.toInt / SquareSizePx
+
+ if (inBounds(x, y))
+ clickSquare(board(x)(y))
+ }
+
+ // Build the status bar
+ val statusBar = jQuery("<p>")
+ statusBar.append(resetButton)
+ statusBar.append(status)
+ statusBar.append(passButton)
+ playground.append(statusBar)
+ }
+
+ // The Game ------------------------------------------------------------------
+
+ def reset() {
+ startGame()
+ }
+
+ @JSExport
+ def startGame() {
+ // Set up the board
+ allSquares foreach (_.owner = NoPlayer)
+ board(3)(3).owner = White
+ board(3)(4).owner = Black
+ board(4)(3).owner = Black
+ board(4)(4).owner = White
+
+ // White begins
+ currentPlayer = White
+
+ // Let's go!
+ startTurn()
+ }
+
+ def startTurn() {
+ val (scoreWhite, scoreBlack) = computeScore()
+ status.text(currentPlayer+"'s turn -- White: "+scoreWhite+
+ " -- Black: "+scoreBlack)
+
+ passButton.prop("disabled", true)
+
+ if (!existsValidMove()) {
+ // Test if the other player can do something
+ currentPlayer = currentPlayer.opponent
+ val opponentCanDoSomething = existsValidMove()
+ currentPlayer = currentPlayer.opponent
+
+ if (opponentCanDoSomething) {
+ passButton.prop("disabled", false)
+ } else {
+ // End of game
+ val winnerText =
+ if (scoreWhite > scoreBlack) "White won!"
+ else if (scoreBlack > scoreWhite) "Black won!"
+ else "Draw"
+ status.text("Game finished -- White: "+scoreWhite+
+ " -- Black: "+scoreBlack+" -- "+winnerText)
+ }
+ }
+ }
+
+ def clickSquare(square: Square) {
+ val toFlip = computeFlips(square)
+ if (!toFlip.isEmpty) {
+ (square :: toFlip) foreach (_.owner = currentPlayer)
+ nextTurn()
+ }
+ }
+
+ def pass() {
+ assert(!existsValidMove())
+ nextTurn()
+ }
+
+ def existsValidMove(): Boolean = {
+ allSquares.exists(isValidMove)
+ }
+
+ def isValidMove(square: Square): Boolean = {
+ !computeFlips(square).isEmpty
+ }
+
+ def computeFlips(square: Square): List[Square] = {
+ if (square.owner != NoPlayer) Nil
+ else {
+ for {
+ i <- (-1 to 1).toList
+ j <- -1 to 1
+ if i != 0 || j != 0
+ flip <- computeFlipsInDirection(square.x, square.y, i, j)
+ } yield flip
+ }
+ }
+
+ def computeFlipsInDirection(x: Int, y: Int,
+ dirx: Int, diry: Int): List[Square] = {
+
+ val allInDir = allSquaresInDirection(x, y, dirx, diry)
+ val (toFlip, remaining) =
+ allInDir.span(_.owner == currentPlayer.opponent)
+
+ val success = remaining.headOption.exists(_.owner == currentPlayer)
+ if (success) toFlip
+ else Nil
+ }
+
+ def allSquaresInDirection(fromx: Int, fromy: Int,
+ dirx: Int, diry: Int): List[Square] = {
+ val nextx = fromx + dirx
+ val nexty = fromy + diry
+ if (inBounds(nextx, nexty))
+ board(nextx)(nexty) :: allSquaresInDirection(nextx, nexty, dirx, diry)
+ else
+ Nil
+ }
+
+ def computeScore(): (Int, Int) = {
+ allSquares.foldLeft((0, 0)) { case ((white, black), square) =>
+ square.owner match {
+ case White => (white+1, black)
+ case Black => (white, black+1)
+ case NoPlayer => (white, black)
+ }
+ }
+ }
+
+ def nextTurn() {
+ currentPlayer = currentPlayer.opponent
+ startTurn()
+ }
+}
diff --git a/examples/reversi/reversi-2.10-fastopt.html b/examples/reversi/reversi-2.10-fastopt.html
new file mode 100644
index 0000000..46cd1c7
--- /dev/null
+++ b/examples/reversi/reversi-2.10-fastopt.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Reversi - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<h1>Reversi - Scala.js example</h1>
+
+<p>Somewhat inspired by
+<a href="http://davidbau.com/reversi/">http://davidbau.com/reversi/</a></p>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/reversi-fastopt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ var mainInstance = new Reversi(
+ jQuery, jQuery("#playground"));
+ mainInstance.startGame();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/reversi/reversi-2.10.html b/examples/reversi/reversi-2.10.html
new file mode 100644
index 0000000..5f7b696
--- /dev/null
+++ b/examples/reversi/reversi-2.10.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Reversi - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<h1>Reversi - Scala.js example</h1>
+
+<p>Somewhat inspired by
+<a href="http://davidbau.com/reversi/">http://davidbau.com/reversi/</a></p>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.10/reversi-opt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ var mainInstance = new Reversi(
+ jQuery, jQuery("#playground"));
+ mainInstance.startGame();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/reversi/reversi-2.11-fastopt.html b/examples/reversi/reversi-2.11-fastopt.html
new file mode 100644
index 0000000..524e716
--- /dev/null
+++ b/examples/reversi/reversi-2.11-fastopt.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Reversi - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<h1>Reversi - Scala.js example</h1>
+
+<p>Somewhat inspired by
+<a href="http://davidbau.com/reversi/">http://davidbau.com/reversi/</a></p>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/reversi-fastopt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ var mainInstance = new Reversi(
+ jQuery, jQuery("#playground"));
+ mainInstance.startGame();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/reversi/reversi-2.11.html b/examples/reversi/reversi-2.11.html
new file mode 100644
index 0000000..b1a6d08
--- /dev/null
+++ b/examples/reversi/reversi-2.11.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Reversi - Scala.js example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<h1>Reversi - Scala.js example</h1>
+
+<p>Somewhat inspired by
+<a href="http://davidbau.com/reversi/">http://davidbau.com/reversi/</a></p>
+
+<div id="playground">
+</div>
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+
+<script type="text/javascript" src="./target/scala-2.11/reversi-opt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ var mainInstance = new Reversi(
+ jQuery, jQuery("#playground"));
+ mainInstance.startGame();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/testing/src/main/scala/ElementCreator.scala b/examples/testing/src/main/scala/ElementCreator.scala
new file mode 100644
index 0000000..ccb3600
--- /dev/null
+++ b/examples/testing/src/main/scala/ElementCreator.scala
@@ -0,0 +1,7 @@
+import scala.scalajs.js.Dynamic.global
+
+object ElementCreator {
+ val jQ = global.jQuery
+
+ def create() = jQ("body").append(jQ("<h1>Test</h1>"))
+}
diff --git a/examples/testing/src/test/scala/CollectionTest.scala b/examples/testing/src/test/scala/CollectionTest.scala
new file mode 100644
index 0000000..a586ca2
--- /dev/null
+++ b/examples/testing/src/test/scala/CollectionTest.scala
@@ -0,0 +1,17 @@
+import scala.scalajs.js
+import scala.scalajs.js.Dynamic.global
+import scala.scalajs.js.JSConverters._
+
+import org.scalajs.jasminetest.JasmineTest
+
+object CollectionTest extends JasmineTest {
+
+ describe("Array") {
+
+ it("should be able to map and filter integers") {
+ val array = Array(5, 7, 2, 6, -30, 33, 66, 76, 75, 0)
+ val result = array.filter(_.toInt % 3 != 0).map(x => x*x)
+ expect(result.toJSArray).toEqual(js.Array(25, 49, 4, 76*76))
+ }
+ }
+}
diff --git a/examples/testing/src/test/scala/ElementCreatorTest.scala b/examples/testing/src/test/scala/ElementCreatorTest.scala
new file mode 100644
index 0000000..43f6756
--- /dev/null
+++ b/examples/testing/src/test/scala/ElementCreatorTest.scala
@@ -0,0 +1,24 @@
+import scala.scalajs.js
+import scala.scalajs.js.Dynamic.global
+
+import org.scalajs.jasminetest.JasmineTest
+
+object ElementCreatorTest extends JasmineTest {
+
+ describe("ElementCreator") {
+
+ it("should be able to create an element in the body") {
+ // create the element
+ ElementCreator.create()
+
+ // jquery would make this easier, but I wanted to
+ // only use pure html in the test itself
+ val body = global.document.getElementsByTagName("body")
+ .asInstanceOf[js.Array[js.Dynamic]].head
+
+ // the Scala.js DOM API would make this easier
+ expect(body.lastChild.tagName.toString == "H1").toBeTruthy
+ expect(body.lastChild.innerHTML.toString == "Test").toBeTruthy
+ }
+ }
+}
diff --git a/examples/testing/testing-2.10-fastopt.html b/examples/testing/testing-2.10-fastopt.html
new file mode 100644
index 0000000..04ded2f
--- /dev/null
+++ b/examples/testing/testing-2.10-fastopt.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Testing - Jasmine HTML reporter example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css"></link>
+</head>
+<body>
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
+<script type="text/javascript" src="./target/scala-2.10/testing-test-fastopt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ // Load tests
+ CollectionTest();
+ ElementCreatorTest();
+
+ // Setup and run Jasmine
+ var jasmineEnv = jasmine.getEnv();
+ var htmlReporter = new jasmine.HtmlReporter();
+ jasmineEnv.addReporter(htmlReporter);
+ jasmineEnv.specFilter = function(spec) {
+ return htmlReporter.specFilter(spec);
+ };
+ jasmineEnv.execute();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/testing/testing-2.10.html b/examples/testing/testing-2.10.html
new file mode 100644
index 0000000..bbb0cfe
--- /dev/null
+++ b/examples/testing/testing-2.10.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Testing - Jasmine HTML reporter example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css"></link>
+</head>
+<body>
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
+<script type="text/javascript" src="./target/scala-2.10/testing-test-opt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ // Load tests
+ CollectionTest();
+ ElementCreatorTest();
+
+ // Setup and run Jasmine
+ var jasmineEnv = jasmine.getEnv();
+ var htmlReporter = new jasmine.HtmlReporter();
+ jasmineEnv.addReporter(htmlReporter);
+ jasmineEnv.specFilter = function(spec) {
+ return htmlReporter.specFilter(spec);
+ };
+ jasmineEnv.execute();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/testing/testing-2.11-fastopt.html b/examples/testing/testing-2.11-fastopt.html
new file mode 100644
index 0000000..a87f635
--- /dev/null
+++ b/examples/testing/testing-2.11-fastopt.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Testing - Jasmine HTML reporter example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css"></link>
+</head>
+<body>
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
+<script type="text/javascript" src="./target/scala-2.11/testing-test-fastopt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ // Load tests
+ CollectionTest();
+ ElementCreatorTest();
+
+ // Setup and run Jasmine
+ var jasmineEnv = jasmine.getEnv();
+ var htmlReporter = new jasmine.HtmlReporter();
+ jasmineEnv.addReporter(htmlReporter);
+ jasmineEnv.specFilter = function(spec) {
+ return htmlReporter.specFilter(spec);
+ };
+ jasmineEnv.execute();
+});
+</script>
+
+</body>
+</html>
diff --git a/examples/testing/testing-2.11.html b/examples/testing/testing-2.11.html
new file mode 100644
index 0000000..9902c3f
--- /dev/null
+++ b/examples/testing/testing-2.11.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Testing - Jasmine HTML reporter example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css"></link>
+</head>
+<body>
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
+<script type="text/javascript" src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
+<script type="text/javascript" src="./target/scala-2.11/testing-test-opt.js"></script>
+
+<script type="text/javascript">
+$(function() {
+ // Load tests
+ CollectionTest();
+ ElementCreatorTest();
+
+ // Setup and run Jasmine
+ var jasmineEnv = jasmine.getEnv();
+ var htmlReporter = new jasmine.HtmlReporter();
+ jasmineEnv.addReporter(htmlReporter);
+ jasmineEnv.specFilter = function(spec) {
+ return htmlReporter.specFilter(spec);
+ };
+ jasmineEnv.execute();
+});
+</script>
+
+</body>
+</html>