Skip to content

Commit c90d355

Browse files
committed
Add ParameterType in the DSL
1 parent 323cb6b commit c90d355

File tree

10 files changed

+399
-11
lines changed

10 files changed

+399
-11
lines changed

scala/sources/gen.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,25 @@ for (i <- 1 to 22) {
1313

1414
println(p1 + p2 + " = { " + register + pf + closeRegister + "\n")
1515
}
16+
17+
/*
18+
* Generates the apply methods in ParameterTypeDsl for Function1 to Function22
19+
*/
20+
for (i <- 1 to 22) {
21+
// String, String, ..., String
22+
val types = (1 to i).map(_ => "String").mkString(", ")
23+
// p1, p2, ..., p22
24+
val args = (1 to i).map(j => s"p$j").mkString(", ")
25+
26+
val template =
27+
s"""
28+
|def apply[R](f: ($types) => R)(implicit tag: ClassTag[R]): Unit = {
29+
| register {
30+
| case List($args) =>
31+
| f($args)
32+
| }
33+
|}
34+
|""".stripMargin
35+
36+
println(template)
37+
}

scala/sources/src/main/scala/io/cucumber/scala/GlueAdaptor.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class GlueAdaptor(glue: Glue) {
1818
registry.beforeStepHooks.map(ScalaHookDefinition(_, scenarioScoped)).foreach(glue.addBeforeStepHook)
1919
registry.docStringTypes.map(ScalaDocStringTypeDefinition(_, scenarioScoped)).foreach(glue.addDocStringType)
2020
registry.dataTableTypes.map(ScalaDataTableTypeDefinition(_, scenarioScoped)).foreach(glue.addDataTableType)
21+
registry.parameterTypes.map(ScalaParameterTypeDefinition(_, scenarioScoped)).foreach(glue.addParameterType)
2122
}
2223

2324
}

scala/sources/src/main/scala/io/cucumber/scala/ScalaDsl.scala

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ private[scala] trait BaseScalaDsl {
2222
/**
2323
* Base trait for a scala step definition implementation.
2424
*/
25-
trait ScalaDsl extends BaseScalaDsl with StepDsl with HookDsl with DataTableTypeDsl with DocStringTypeDsl {
25+
trait ScalaDsl extends BaseScalaDsl with StepDsl with HookDsl with DataTableTypeDsl with DocStringTypeDsl with ParameterTypeDsl {
2626

2727
}
2828

@@ -134,6 +134,176 @@ private[scala] trait DataTableTypeDsl extends BaseScalaDsl {
134134

135135
}
136136

137+
private[scala] trait ParameterTypeDsl extends BaseScalaDsl {
138+
139+
def ParameterType(name: String, regex: String) = new ParameterTypeBody(name, regex)
140+
141+
final class ParameterTypeBody(name: String, regex: String) {
142+
143+
// Important: use the piece of code in the file gen.scala to generate these methods easily
144+
145+
def apply[R](f: (String) => R)(implicit tag: ClassTag[R]): Unit = {
146+
register {
147+
case List(p1) =>
148+
f(p1)
149+
}
150+
}
151+
152+
def apply[R](f: (String, String) => R)(implicit tag: ClassTag[R]): Unit = {
153+
register {
154+
case List(p1, p2) =>
155+
f(p1, p2)
156+
}
157+
}
158+
159+
def apply[R](f: (String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
160+
register {
161+
case List(p1, p2, p3) =>
162+
f(p1, p2, p3)
163+
}
164+
}
165+
166+
def apply[R](f: (String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
167+
register {
168+
case List(p1, p2, p3, p4) =>
169+
f(p1, p2, p3, p4)
170+
}
171+
}
172+
173+
def apply[R](f: (String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
174+
register {
175+
case List(p1, p2, p3, p4, p5) =>
176+
f(p1, p2, p3, p4, p5)
177+
}
178+
}
179+
180+
def apply[R](f: (String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
181+
register {
182+
case List(p1, p2, p3, p4, p5, p6) =>
183+
f(p1, p2, p3, p4, p5, p6)
184+
}
185+
}
186+
187+
def apply[R](f: (String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
188+
register {
189+
case List(p1, p2, p3, p4, p5, p6, p7) =>
190+
f(p1, p2, p3, p4, p5, p6, p7)
191+
}
192+
}
193+
194+
def apply[R](f: (String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
195+
register {
196+
case List(p1, p2, p3, p4, p5, p6, p7, p8) =>
197+
f(p1, p2, p3, p4, p5, p6, p7, p8)
198+
}
199+
}
200+
201+
def apply[R](f: (String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
202+
register {
203+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9) =>
204+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9)
205+
}
206+
}
207+
208+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
209+
register {
210+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) =>
211+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
212+
}
213+
}
214+
215+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
216+
register {
217+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) =>
218+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
219+
}
220+
}
221+
222+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
223+
register {
224+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) =>
225+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)
226+
}
227+
}
228+
229+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
230+
register {
231+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) =>
232+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)
233+
}
234+
}
235+
236+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
237+
register {
238+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) =>
239+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)
240+
}
241+
}
242+
243+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
244+
register {
245+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) =>
246+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)
247+
}
248+
}
249+
250+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
251+
register {
252+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) =>
253+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)
254+
}
255+
}
256+
257+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
258+
register {
259+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) =>
260+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)
261+
}
262+
}
263+
264+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
265+
register {
266+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) =>
267+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)
268+
}
269+
}
270+
271+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
272+
register {
273+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) =>
274+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)
275+
}
276+
}
277+
278+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
279+
register {
280+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20) =>
281+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)
282+
}
283+
}
284+
285+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
286+
register {
287+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21) =>
288+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21)
289+
}
290+
}
291+
292+
def apply[R](f: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) => R)(implicit tag: ClassTag[R]): Unit = {
293+
register {
294+
case List(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22) =>
295+
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22)
296+
}
297+
}
298+
299+
private def register[R](pf: PartialFunction[List[String], R])(implicit tag: ClassTag[R]): Unit = {
300+
registry.parameterTypes += ScalaParameterTypeDetails[R](name, regex, pf, tag)
301+
}
302+
303+
}
304+
305+
}
306+
137307
private[scala] trait StepDsl extends BaseScalaDsl {
138308
self =>
139309

scala/sources/src/main/scala/io/cucumber/scala/ScalaDslRegistry.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ class ScalaDslRegistry {
1818

1919
val dataTableTypes = new ArrayBuffer[ScalaDataTableTypeDetails[_]]
2020

21+
val parameterTypes = new ArrayBuffer[ScalaParameterTypeDetails[_]]
22+
2123
}
2224

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package io.cucumber.scala
2+
3+
import io.cucumber.core.backend.{ParameterTypeDefinition, ScenarioScoped}
4+
import io.cucumber.cucumberexpressions.{CaptureGroupTransformer, ParameterType}
5+
6+
import scala.collection.JavaConverters._
7+
8+
trait ScalaParameterTypeDefinition[R] extends ParameterTypeDefinition with AbstractGlueDefinition {
9+
10+
val details: ScalaParameterTypeDetails[R]
11+
12+
override val location: StackTraceElement = new Exception().getStackTrace()(3)
13+
14+
private val transformer: CaptureGroupTransformer[R] = new CaptureGroupTransformer[R] {
15+
override def transform(parameterContent: Array[String]): R = {
16+
details.body.apply(parameterContent.toList)
17+
}
18+
}
19+
20+
override val parameterType: ParameterType[R] = new ParameterType[R](details.name, Seq(details.regex).asJava, details.tag.runtimeClass.asInstanceOf[Class[R]], transformer)
21+
22+
}
23+
24+
object ScalaParameterTypeDefinition {
25+
26+
def apply[R](stepDetails: ScalaParameterTypeDetails[R], scenarioScoped: Boolean): ScalaParameterTypeDefinition[R] = {
27+
if (scenarioScoped) {
28+
new ScalaScenarioScopedParameterTypeDefinition(stepDetails)
29+
} else {
30+
new ScalaGlobalParameterTypeDefinition(stepDetails)
31+
}
32+
}
33+
34+
}
35+
36+
class ScalaScenarioScopedParameterTypeDefinition[R](override val details: ScalaParameterTypeDetails[R]) extends ScalaParameterTypeDefinition[R] with ScenarioScoped {
37+
}
38+
39+
class ScalaGlobalParameterTypeDefinition[R](override val details: ScalaParameterTypeDetails[R]) extends ScalaParameterTypeDefinition[R] {
40+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.cucumber.scala
2+
3+
import scala.reflect.ClassTag
4+
5+
case class ScalaParameterTypeDetails[R](name: String, regex: String, body: List[String] => R, tag: ClassTag[R])
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Feature: As Cucumber Scala, I want to handle ParameterType definitions
2+
3+
Scenario: define parameter type with single argument
4+
Given string builder parameter, defined by lambda
5+
6+
Scenario: define parameter type with two arguments
7+
Given balloon coordinates 123,456, defined by lambda
8+
9+
Scenario: define parameter type with three arguments
10+
Given kebab made from mushroom, meat and veg, defined by lambda

0 commit comments

Comments
 (0)