Skip to content

Commit d9ddefb

Browse files
committed
feat: 🚀 Support generic types in DocStringType definitions
1 parent 3f60c92 commit d9ddefb

File tree

7 files changed

+91
-20
lines changed

7 files changed

+91
-20
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ See also the [CHANGELOG](https://github.com/cucumber/cucumber-jvm/blob/master/CH
1111

1212
### Added
1313

14+
- [Scala] Support generic types in `DocStringType`
15+
1416
### Changed
1517

1618
- [Core] Updated `cucumber-core` dependency to [7.2.0](https://github.com/cucumber/cucumber-jvm/blob/main/CHANGELOG.md)

‎cucumber-scala/src/main/scala/io/cucumber/scala/DocStringTypeDsl.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package io.cucumber.scala
22

33
import io.cucumber.scala.Aliases.DocStringDefinitionBody
44

5-
import scala.reflect.ClassTag
6-
75
private[scala] trait DocStringTypeDsl extends BaseScalaDsl {
86

97
/** Register doc string type.
@@ -15,9 +13,9 @@ private[scala] trait DocStringTypeDsl extends BaseScalaDsl {
1513
*/
1614
def DocStringType[T](
1715
contentType: String
18-
)(body: DocStringDefinitionBody[T])(implicit ev: ClassTag[T]): Unit = {
16+
)(body: DocStringDefinitionBody[T])(implicit ev: Stepable[T]): Unit = {
1917
registry.registerDocStringType(
20-
ScalaDocStringTypeDetails[T](contentType, body, ev)
18+
ScalaDocStringTypeDetails[T](contentType, body, ev.asJavaType)
2119
)
2220
}
2321

‎cucumber-scala/src/main/scala/io/cucumber/scala/ScalaDocStringTypeDefinition.scala

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,20 @@ import io.cucumber.core.backend.{DocStringTypeDefinition, ScenarioScoped}
44
import io.cucumber.docstring.DocStringType
55
import io.cucumber.docstring.DocStringType.Transformer
66

7-
import scala.reflect.ClassTag
8-
9-
trait ScalaDocStringTypeDefinition[T]
7+
abstract class ScalaDocStringTypeDefinition[T]
108
extends DocStringTypeDefinition
119
with AbstractGlueDefinition {
1210

1311
val details: ScalaDocStringTypeDetails[T]
1412

15-
implicit val ev: ClassTag[T]
16-
1713
override val location: StackTraceElement = new Exception().getStackTrace()(3)
1814

1915
private val transformer: Transformer[T] = (s: String) => {
2016
details.body.apply(s)
2117
}
2218

2319
override val docStringType: DocStringType =
24-
new DocStringType(ev.runtimeClass, details.contentType, transformer)
20+
new DocStringType(details.`type`, details.contentType, transformer)
2521

2622
}
2723

@@ -32,21 +28,19 @@ object ScalaDocStringTypeDefinition {
3228
scenarioScoped: Boolean
3329
): ScalaDocStringTypeDefinition[T] = {
3430
if (scenarioScoped) {
35-
new ScalaScenarioScopedDocStringTypeDefinition(details)(details.tag)
31+
new ScalaScenarioScopedDocStringTypeDefinition(details)
3632
} else {
37-
new ScalaGlobalDocStringTypeDefinition(details)(details.tag)
33+
new ScalaGlobalDocStringTypeDefinition(details)
3834
}
3935
}
4036

4137
}
4238

4339
class ScalaScenarioScopedDocStringTypeDefinition[T](
4440
override val details: ScalaDocStringTypeDetails[T]
45-
)(implicit val ev: ClassTag[T])
46-
extends ScalaDocStringTypeDefinition[T]
41+
) extends ScalaDocStringTypeDefinition[T]
4742
with ScenarioScoped {}
4843

4944
class ScalaGlobalDocStringTypeDefinition[T](
5045
override val details: ScalaDocStringTypeDetails[T]
51-
)(implicit val ev: ClassTag[T])
52-
extends ScalaDocStringTypeDefinition[T] {}
46+
) extends ScalaDocStringTypeDefinition[T] {}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package io.cucumber.scala
22

3-
import Aliases.DocStringDefinitionBody
3+
import io.cucumber.scala.Aliases.DocStringDefinitionBody
44

5-
import scala.reflect.ClassTag
5+
import java.lang.reflect.{Type => JType}
66

77
case class ScalaDocStringTypeDetails[T](
88
contentType: String,
99
body: DocStringDefinitionBody[T],
10-
tag: ClassTag[T]
10+
`type`: JType
1111
)

‎cucumber-scala/src/main/scala/io/cucumber/scala/Stepable.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ object Stepable {
219219

220220
}
221221

222-
class ScalaParameterizedType(self: JavaType, args: Array[JavaType])
222+
class ScalaParameterizedType(val self: JavaType, val args: Array[JavaType])
223223
extends JavaParameterizedType {
224224

225225
override def getActualTypeArguments: Array[JavaType] = args
@@ -228,4 +228,13 @@ class ScalaParameterizedType(self: JavaType, args: Array[JavaType])
228228

229229
override def getOwnerType: JavaType = null
230230

231+
override def getTypeName: String =
232+
self.getTypeName + args.map(_.getTypeName).mkString("[", ",", "]")
233+
234+
override def equals(obj: Any): Boolean = obj match {
235+
case x: ScalaParameterizedType =>
236+
x.self == self && (x.args sameElements args)
237+
case _ => false
238+
}
239+
231240
}

‎cucumber-scala/src/test/resources/tests/docstring/Docstring.feature

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,26 @@ Feature: As Cucumber Scala, I want to use DocStringType
1515
<xml></xml>
1616
"""
1717
Then I have a xml text
18+
19+
Scenario: Using no content type
20+
Given the following raw text
21+
"""
22+
something raw
23+
"""
24+
Then I have a raw text
25+
26+
Scenario: Generic type - string
27+
Given the following string list
28+
"""
29+
item 1
30+
item 2
31+
"""
32+
Then I have a string list "item 1,item 2"
33+
34+
Scenario: Generic type - int
35+
Given the following int list
36+
"""
37+
1
38+
2
39+
"""
40+
Then I have a int list "1,2"

‎cucumber-scala/src/test/scala/tests/docstring/DocStringSteps.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class DocStringSteps extends ScalaDsl with EN {
88

99
case class XmlText(xml: String)
1010

11+
case class RawText(raw: String)
12+
1113
var _text: Any = _
1214

1315
DocStringType("json") { (text) =>
@@ -18,6 +20,19 @@ class DocStringSteps extends ScalaDsl with EN {
1820
XmlText(text)
1921
}
2022

23+
DocStringType("") { (text) =>
24+
RawText(text)
25+
}
26+
27+
// Tests generic type
28+
DocStringType[Seq[String]]("") { (text) =>
29+
text.split('\n').toSeq
30+
}
31+
32+
DocStringType[Seq[Int]]("") { (text) =>
33+
text.split('\n').map(_.toInt).toSeq
34+
}
35+
2136
Given("the following json text") { (json: JsonText) =>
2237
_text = json
2338
}
@@ -26,6 +41,18 @@ class DocStringSteps extends ScalaDsl with EN {
2641
_text = xml
2742
}
2843

44+
Given("the following raw text") { (raw: RawText) =>
45+
_text = raw
46+
}
47+
48+
Given("the following string list") { (list: Seq[String]) =>
49+
_text = list
50+
}
51+
52+
Given("the following int list") { (list: Seq[Int]) =>
53+
_text = list
54+
}
55+
2956
Then("I have a json text") {
3057
assert(_text.isInstanceOf[JsonText])
3158
}
@@ -34,4 +61,22 @@ class DocStringSteps extends ScalaDsl with EN {
3461
assert(_text.isInstanceOf[XmlText])
3562
}
3663

64+
Then("I have a raw text") {
65+
assert(_text.isInstanceOf[RawText])
66+
}
67+
68+
Then("I have a string list {string}") { (expectedList: String) =>
69+
assert(_text.isInstanceOf[Seq[_]])
70+
assert(_text.asInstanceOf[Seq[_]].head.isInstanceOf[String])
71+
assert(_text.asInstanceOf[Seq[String]] == expectedList.split(',').toSeq)
72+
}
73+
74+
Then("I have a int list {string}") { (expectedList: String) =>
75+
assert(_text.isInstanceOf[Seq[_]])
76+
assert(_text.asInstanceOf[Seq[_]].head.isInstanceOf[Int])
77+
assert(
78+
_text.asInstanceOf[Seq[Int]] == expectedList.split(',').map(_.toInt).toSeq
79+
)
80+
}
81+
3782
}

0 commit comments

Comments
 (0)