Skip to content

Commit

Permalink
add scala-js test
Browse files Browse the repository at this point in the history
  • Loading branch information
xuwei-k committed Dec 30, 2017
1 parent 69a7381 commit 099109a
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 125 deletions.
22 changes: 21 additions & 1 deletion build.sbt
Expand Up @@ -30,13 +30,33 @@ lazy val scopt = (crossProject(JSPlatform, JVMPlatform, NativePlatform) in file(
siteSubdirName in SiteScaladoc := "$v/api",
git.remoteRepo := "git@github.com:scopt/scopt.git",
description := """a command line options parsing library""",
libraryDependencies += specs2.value % Test,
scalacOptions ++= Seq("-language:existentials"),
resolvers += "sonatype-public" at "https://oss.sonatype.org/content/repositories/public",
// scaladoc fix
unmanagedClasspath in Compile += Attributed.blank(new java.io.File("doesnotexist"))
).
platformsSettings(JVMPlatform, JSPlatform)(
libraryDependencies += specs2.value % Test,
libraryDependencies ++= parserCombinators.value
).
jsSettings(
scalaJSModuleKind := ModuleKind.CommonJSModule,
sources in Test := {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 10)) =>
// specs 4.x does not support scala 2.10
// specs 3.x does not support scala-js
Nil
case Some((2, v)) if v >= 13 =>
// https://github.com/scala/scala-parser-combinators/issues/119
Nil
case _ =>
(sources in Test).value
}
}
).
nativeSettings(
sources in Test := Nil, // https://github.com/etorreborre/specs2/issues/591
scalaVersion := scala211,
crossScalaVersions := Nil
)
Expand Down
3 changes: 3 additions & 0 deletions js/src/test/scala/scopt/SpecUtilPlatform.scala
@@ -0,0 +1,3 @@
object SpecUtilPlatform {
val envLineSeparator = "\n"
}
73 changes: 73 additions & 0 deletions jvm/src/test/scala/scopt/ImmutableParserSpecJVM.scala
@@ -0,0 +1,73 @@
import org.specs2._
import java.util.{Calendar, GregorianCalendar}
import java.io.{ByteArrayOutputStream, File}
import java.net.{ URI, InetAddress }
import scala.concurrent.duration.Duration

class ImmutableParserSpecJVM extends Specification { def is = args(sequential = true) ^ s2"""
This is a specification to check the immutable parser

opt[Calendar]("foo") action { x => x } should
parse 2000-01-01 out of --foo 2000-01-01 ${calendarParser("--foo", "2000-01-01")}
parse 2000-01-01 out of --foo=2000-01-01 ${calendarParser("--foo=2000-01-01")}
fail to parse --foo bar ${calendarParserFail("--foo", "bar")}
fail to parse --foo=bar ${calendarParserFail("--foo=bar")}

opt[File]("foo") action { x => x } should
parse test.txt out of --foo test.txt ${fileParser("--foo", "test.txt")}
parse test.txt out of --foo=test.txt ${fileParser("--foo=test.txt")}

opt[InetAddress]("foo") action { x => x } should
parse 8.8.8.8 out of --foo 8.8.8.8 ${inetAddressParser("--foo", "8.8.8.8")}
parse 8.8.8.8 out of --foo=8.8.8.8 ${inetAddressParser("--foo=8.8.8.8")}
"""

import SpecUtil._

val calendarParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[Calendar]("foo").action( (x, c) => c.copy(calendarValue = x) )
help("help")
}
def calendarParser(args: String*) = {
val result = calendarParser1.parse(args.toSeq, Config())
result.get.calendarValue.getTime === new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime
}
def calendarParserFail(args: String*) = {
val result = calendarParser1.parse(args.toSeq, Config())
result === None
}

val fileParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[File]("foo").action( (x, c) => c.copy(fileValue = x) )
help("help")
}
def fileParser(args: String*) = {
val result = fileParser1.parse(args.toSeq, Config())
result.get.fileValue === new File("test.txt")
}

val inetAddressParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[InetAddress]("foo").action( (x, c) => c.copy(inetAddressValue = x) )
help("help")
}
def inetAddressParser(args: String*) = {
val result = inetAddressParser1.parse(args.toSeq, Config())
result.get.inetAddressValue === InetAddress.getByName("8.8.8.8")
}

case class Config(flag: Boolean = false, intValue: Int = 0, longValue: Long = 0L, stringValue: String = "",
doubleValue: Double = 0.0, boolValue: Boolean = false, debug: Boolean = false,
bigDecimalValue: BigDecimal = BigDecimal("0.0"),
calendarValue: Calendar = new GregorianCalendar(1900, Calendar.JANUARY, 1),
fileValue: File = new File("."),
uriValue: URI = new URI("http://localhost"),
inetAddressValue: InetAddress = InetAddress.getByName("0.0.0.0"),
durationValue: Duration = Duration("0s"),
key: String = "", a: String = "", b: String = "",
seqInts: Seq[Int] = Seq(),
mapStringToBool: Map[String,Boolean] = Map(),
seqTupleStringString: Seq[(String, String)] = Nil, charValue: Char = 0)
}
3 changes: 3 additions & 0 deletions jvm/src/test/scala/scopt/SpecUtilPlatform.scala
@@ -0,0 +1,3 @@
object SpecUtilPlatform {
val envLineSeparator = util.Properties.lineSeparator
}
22 changes: 18 additions & 4 deletions project/Dependencies.scala
@@ -1,5 +1,6 @@
import sbt._
import Keys._
import sbtcrossproject.CrossPlugin.autoImport._

object Dependencies {
lazy val scala210 = "2.10.7"
Expand All @@ -8,12 +9,25 @@ object Dependencies {
lazy val scala213 = "2.13.0-M2"

lazy val specs2 = Def.setting {
val v = CrossVersion.partialVersion(scalaVersion.value) match {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 10)) =>
"3.9.5" // specs2 4.x does not support Scala 2.10
// specs2 4.x does not support Scala 2.10
"org.specs2" %% "specs2-core" % "3.9.5"
case _ =>
"4.0.2"
// https://github.com/scala/scala-parser-combinators/issues/119
"org.specs2" %%% "specs2-core" % "4.0.2" exclude("org.scala-lang.modules", "scala-parser-combinators_" + scalaBinaryVersion.value)
}
}

lazy val parserCombinators = Def.setting {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 10)) =>
Nil
case Some((2, v)) if v >= 13 =>
Seq("org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.6" % Test)
case _ =>
// https://github.com/scala/scala-parser-combinators/issues/119
Seq("org.scala-lang.modules" %%% "scala-parser-combinators" % "1.0.5" % Test)
}
"org.specs2" %% "specs2-core" % v
}
}
@@ -1,7 +1,6 @@
import org.specs2._
import java.util.{Calendar, GregorianCalendar}
import java.io.{ByteArrayOutputStream, File}
import java.net.{ URI, InetAddress }
import java.io.ByteArrayOutputStream
import java.net.URI
import scala.concurrent.duration.Duration

class ImmutableParserSpec extends Specification { def is = args(sequential = true) ^ s2"""
Expand Down Expand Up @@ -78,24 +77,10 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
fail to parse --foo bar ${bigDecimalParserFail("--foo", "bar")}
fail to parse --foo=bar ${bigDecimalParserFail("--foo=bar")}

opt[Calendar]("foo") action { x => x } should
parse 2000-01-01 out of --foo 2000-01-01 ${calendarParser("--foo", "2000-01-01")}
parse 2000-01-01 out of --foo=2000-01-01 ${calendarParser("--foo=2000-01-01")}
fail to parse --foo bar ${calendarParserFail("--foo", "bar")}
fail to parse --foo=bar ${calendarParserFail("--foo=bar")}

opt[File]("foo") action { x => x } should
parse test.txt out of --foo test.txt ${fileParser("--foo", "test.txt")}
parse test.txt out of --foo=test.txt ${fileParser("--foo=test.txt")}

opt[URI]("foo") action { x => x } should
parse http://github.com/ out of --foo http://github.com/ ${uriParser("--foo", "http://github.com/")}
parse http://github.com/ out of --foo=http://github.com/ ${uriParser("--foo=http://github.com/")}

opt[InetAddress]("foo") action { x => x } should
parse 8.8.8.8 out of --foo 8.8.8.8 ${inetAddressParser("--foo", "8.8.8.8")}
parse 8.8.8.8 out of --foo=8.8.8.8 ${inetAddressParser("--foo=8.8.8.8")}

opt[Duration]("foo") action { x => x } should
parse 30s out of --foo 30s ${durationParser("--foo", "30s")}
parse 30s out of --foo=30s ${durationParser("--foo=30s")}
Expand Down Expand Up @@ -319,30 +304,6 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
result === None
}

val calendarParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[Calendar]("foo").action( (x, c) => c.copy(calendarValue = x) )
help("help")
}
def calendarParser(args: String*) = {
val result = calendarParser1.parse(args.toSeq, Config())
result.get.calendarValue.getTime === new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime
}
def calendarParserFail(args: String*) = {
val result = calendarParser1.parse(args.toSeq, Config())
result === None
}

val fileParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[File]("foo").action( (x, c) => c.copy(fileValue = x) )
help("help")
}
def fileParser(args: String*) = {
val result = fileParser1.parse(args.toSeq, Config())
result.get.fileValue === new File("test.txt")
}

val uriParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[URI]("foo").action( (x, c) => c.copy(uriValue = x) )
Expand All @@ -353,16 +314,6 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
result.get.uriValue === new URI("http://github.com/")
}

val inetAddressParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[InetAddress]("foo").action( (x, c) => c.copy(inetAddressValue = x) )
help("help")
}
def inetAddressParser(args: String*) = {
val result = inetAddressParser1.parse(args.toSeq, Config())
result.get.inetAddressValue === InetAddress.getByName("8.8.8.8")
}

val durationParser1 = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")
opt[Duration]("foo").action( (x, c) => c.copy(durationValue = x) )
Expand Down Expand Up @@ -583,21 +534,17 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
}

def helpParserOneColumn(args: String*) = {
case class Config(foo: Int = -1, out: File = new File("."), xyz: Boolean = false,
case class Config(foo: Int = -1, xyz: Boolean = false,
libName: String = "", maxCount: Int = -1, verbose: Boolean = false, debug: Boolean = false,
mode: String = "", files: Seq[File] = Seq(), keepalive: Boolean = false,
jars: Seq[File] = Seq(), kwargs: Map[String,String] = Map())
mode: String = "", keepalive: Boolean = false,
kwargs: Map[String,String] = Map())
val parser = new scopt.OptionParser[Config]("scopt") {
override def renderingMode = scopt.RenderingMode.OneColumn
head("scopt", "3.x")

opt[Int]('f', "foo").action( (x, c) =>
c.copy(foo = x) ).text("foo is an integer property")

opt[File]('o', "out").required().valueName("<file>").
action( (x, c) => c.copy(out = x) ).
text("out is a required file property")

opt[(String, Int)]("max").action({
case ((k, v), c) => c.copy(libName = k, maxCount = v) }).
validate( x =>
Expand All @@ -606,9 +553,6 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
keyValueName("<libname>", "<max>").
text("maximum count for <libname>")

opt[Seq[File]]('j', "jars").valueName("<jar1>,<jar2>...").action( (x,c) =>
c.copy(jars = x) ).text("jars to include")

opt[Map[String,String]]("kwargs").valueName("k1=v1,k2=v2...").action( (x, c) =>
c.copy(kwargs = x) ).text("other arguments")

Expand All @@ -620,9 +564,6 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru

help("help").text("prints this usage text")

arg[File]("<file>...").unbounded().optional().action( (x, c) =>
c.copy(files = c.files :+ x) ).text("optional unbounded args")

note("some notes.".newline)

cmd("update").action( (_, c) => c.copy(mode = "update") ).
Expand All @@ -641,24 +582,18 @@ class ImmutableParserSpec extends Specification { def is = args(sequential = tru
}
parser.parse(args.toSeq, Config())
val expectedUsage = """scopt 3.x
Usage: scopt [update] [options] [<file>...]
Usage: scopt [update] [options]
-f <value> | --foo <value>
foo is an integer property
-o <file> | --out <file>
out is a required file property
--max:<libname>=<max>
maximum count for <libname>
-j <jar1>,<jar2>... | --jars <jar1>,<jar2>...
jars to include
--kwargs k1=v1,k2=v2...
other arguments
--verbose
verbose is a flag
--help
prints this usage text
<file>...
optional unbounded args
some notes.
Command: update [options]
Expand All @@ -673,20 +608,16 @@ update is a command.
}

def helpParserTwoColumns(args: String*) = {
case class Config(foo: Int = -1, out: File = new File("."), xyz: Boolean = false,
case class Config(foo: Int = -1, xyz: Boolean = false,
libName: String = "", maxCount: Int = -1, verbose: Boolean = false, debug: Boolean = false,
mode: String = "", files: Seq[File] = Seq(), keepalive: Boolean = false,
jars: Seq[File] = Seq(), kwargs: Map[String,String] = Map())
mode: String = "", keepalive: Boolean = false,
kwargs: Map[String,String] = Map())
val parser = new scopt.OptionParser[Config]("scopt") {
head("scopt", "3.x")

opt[Int]('f', "foo").action( (x, c) =>
c.copy(foo = x) ).text("foo is an integer property")

opt[File]('o', "out").required().valueName("<file>").
action( (x, c) => c.copy(out = x) ).
text("out is a required file property")

opt[(String, Int)]("max").action({
case ((k, v), c) => c.copy(libName = k, maxCount = v) }).
validate( x =>
Expand All @@ -695,9 +626,6 @@ update is a command.
keyValueName("<libname>", "<max>").
text("maximum count for <libname>")

opt[Seq[File]]('j', "jars").valueName("<jar1>,<jar2>...").action( (x,c) =>
c.copy(jars = x) ).text("jars to include")

opt[Map[String,String]]("kwargs").valueName("k1=v1,k2=v2...").action( (x, c) =>
c.copy(kwargs = x) ).text("other arguments")

Expand All @@ -709,9 +637,6 @@ update is a command.

help("help").text("prints this usage text")

arg[File]("<file>...").unbounded().optional().action( (x, c) =>
c.copy(files = c.files :+ x) ).text("optional unbounded args")

note("some notes.".newline)

cmd("update").action( (_, c) => c.copy(mode = "update") ).
Expand All @@ -730,17 +655,13 @@ update is a command.
}
parser.parse(args.toSeq, Config())
val expectedUsage= """scopt 3.x
Usage: scopt [update] [options] [<file>...]
Usage: scopt [update] [options]
-f, --foo <value> foo is an integer property
-o, --out <file> out is a required file property
--max:<libname>=<max> maximum count for <libname>
-j, --jars <jar1>,<jar2>...
jars to include
--kwargs k1=v1,k2=v2... other arguments
--verbose verbose is a flag
--help prints this usage text
<file>... optional unbounded args
some notes.
Command: update [options]
Expand Down Expand Up @@ -825,10 +746,7 @@ Usage: scopt [update] [options]
case class Config(flag: Boolean = false, intValue: Int = 0, longValue: Long = 0L, stringValue: String = "",
doubleValue: Double = 0.0, boolValue: Boolean = false, debug: Boolean = false,
bigDecimalValue: BigDecimal = BigDecimal("0.0"),
calendarValue: Calendar = new GregorianCalendar(1900, Calendar.JANUARY, 1),
fileValue: File = new File("."),
uriValue: URI = new URI("http://localhost"),
inetAddressValue: InetAddress = InetAddress.getByName("0.0.0.0"),
durationValue: Duration = Duration("0s"),
key: String = "", a: String = "", b: String = "",
seqInts: Seq[Int] = Seq(),
Expand Down

0 comments on commit 099109a

Please sign in to comment.