Skip to content

Commit 3e28a1d

Browse files
authored
Merge pull request #57 from cucumber/more-tests-datatables
Add tests and doc about datatables
2 parents fa5a571 + 8526623 commit 3e28a1d

File tree

10 files changed

+300
-28
lines changed

10 files changed

+300
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ The minor version might differ because Cucumber Scala may add Scala-related feat
2929
- Documentation
3030
- [Basic usage](docs/usage.md)
3131
- [Step Definitions](docs/step_definitions.md)
32+
- [DataTables](docs/datatables.md)
3233
- [Hooks](docs/hooks.md)
3334
- [Transformers](docs/transformers.md)
3435
- [Default Jackson DataTable Transformer](docs/default_jackson_datatable_transformer.md)

docs/datatables.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# DataTables
2+
3+
Cucumber Scala support DataTables with Java types.
4+
5+
See below the exhaustive list of possible mappings.
6+
7+
## As Map of Map
8+
9+
```gherkin
10+
Given the following table as Map of Map
11+
| | key1 | key2 | key3 |
12+
| row1 | val11 | val12 | val13 |
13+
| row2 | val21 | val22 | val23 |
14+
| row3 | val31 | val32 | val33 |
15+
```
16+
17+
```scala
18+
Given("the following table as Map of Map") { (table: JavaMap[String, JavaMap[String, String]]) =>
19+
// Map(
20+
// "row1" -> Map("key1" -> "val11", "key2" -> "val12", "key3" -> "val13"),
21+
// "row2" -> Map("key1" -> "val21", "key2" -> "val22", "key3" -> "val23"),
22+
// "row3" -> Map("key1" -> "val31", "key2" -> "val32", "key3" -> "val33")
23+
// )
24+
}
25+
```
26+
27+
## As List of Map
28+
29+
```gherkin
30+
Given the following table as List of Map
31+
| key1 | key2 | key3 |
32+
| val11 | val12 | val13 |
33+
| val21 | val22 | val23 |
34+
| val31 | val32 | val33 |
35+
```
36+
37+
```scala
38+
Given("the following table as List of Map") { (table: JavaList[JavaMap[String, String]]) =>
39+
// Seq(
40+
// Map("key1" -> "val11", "key2" -> "val12", "key3" -> "val13"),
41+
// Map("key1" -> "val21", "key2" -> "val22", "key3" -> "val23"),
42+
// Map("key1" -> "val31", "key2" -> "val32", "key3" -> "val33")
43+
// )
44+
}
45+
```
46+
47+
## As Map of List
48+
49+
```gherkin
50+
Given the following table as Map of List
51+
| row1 | val11 | val12 | val13 |
52+
| row2 | val21 | val22 | val23 |
53+
| row3 | val31 | val32 | val33 |
54+
```
55+
56+
```scala
57+
Given("the following table as Map of List") { (table: JavaMap[String, JavaList[String]]) =>
58+
// Map(
59+
// "row1" -> Seq("val11", "val12", "val13"),
60+
// "row2" -> Seq("val21", "val22", "val23"),
61+
// "row3" -> Seq("val31", "val32", "val33")
62+
// )
63+
}
64+
```
65+
66+
67+
## As List of List
68+
69+
```gherkin
70+
Given the following table as List of List
71+
| val11 | val12 | val13 |
72+
| val21 | val22 | val23 |
73+
| val31 | val32 | val33 |
74+
```
75+
76+
```scala
77+
Given("the following table as List of List") { (table: JavaList[JavaList[String]]) =>
78+
// Seq(
79+
// Seq("val11", "val12", "val13"),
80+
// Seq("val21", "val22", "val23"),
81+
// Seq("val31", "val32", "val33")
82+
// )
83+
}
84+
```
85+
86+
## As Map
87+
88+
```gherkin
89+
Given the following table as Map
90+
| row1 | val11 |
91+
| row2 | val21 |
92+
| row3 | val31 |
93+
```
94+
95+
```scala
96+
Given("the following table as Map") { (table: JavaMap[String, String]) =>
97+
// Map(
98+
// "row1" -> "val11",
99+
// "row2" -> "val21",
100+
// "row3" -> "val31"
101+
// )
102+
}
103+
```
104+
105+
## As List
106+
107+
```gherkin
108+
Given the following table as List
109+
| val11 |
110+
| val21 |
111+
| val31 |
112+
```
113+
114+
```scala
115+
Given("the following table as List") { (table: JavaList[String]) =>
116+
// Seq(
117+
// "val11",
118+
// "val21",
119+
// "val31"
120+
// )
121+
}
122+
```
123+
124+
## As DataTable
125+
126+
```gherkin
127+
Given the following table as DataTable
128+
# Any previous table definition is possible
129+
| key1 | key2 | key3 |
130+
| val11 | val12 | val13 |
131+
| val21 | val22 | val23 |
132+
| val31 | val32 | val33 |
133+
```
134+
135+
```scala
136+
Given("the following table as DataTable") { (table: DataTable) =>
137+
// Use the table any way you want, including any of the options defined previously
138+
}
139+
```

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

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.cucumber.scala
22

3-
import java.lang.reflect.{ParameterizedType, Type}
4-
53
import io.cucumber.scala.Aliases._
64

75
import scala.reflect.ClassTag
@@ -912,25 +910,10 @@ private[scala] trait StepDsl extends BaseScalaDsl {
912910
}
913911
}
914912

915-
private def register(ms: Manifest[_ <: Any]*)(pf: PartialFunction[List[Any], Any]): Unit = {
916-
val types = ms.map(m => toJavaType(m)).toArray
917-
registry.stepDefinitions += ScalaStepDetails(Utils.frame(self), name, regex, types, pf)
913+
private def register(manifests: Manifest[_ <: Any]*)(pf: PartialFunction[List[Any], Any]): Unit = {
914+
registry.stepDefinitions += ScalaStepDetails(Utils.frame(self), name, regex, manifests, pf)
918915
}
919916

920-
private def toJavaType(m: Manifest[_]): Type = {
921-
val typeArgs = m.typeArguments
922-
if (typeArgs.isEmpty) {
923-
m.runtimeClass
924-
} else {
925-
new ParameterizedType {
926-
override def getActualTypeArguments: Array[Type] = typeArgs.map(toJavaType).toArray
927-
928-
override def getRawType: Type = m.runtimeClass
929-
930-
override def getOwnerType: Type = ???
931-
}
932-
}
933-
}
934917
}
935918

936919
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.cucumber.scala
22

3-
import java.lang.reflect.Type
43
import java.util.{List => JList}
54

65
import io.cucumber.core.backend.{ParameterInfo, ScenarioScoped, StepDefinition}
@@ -14,10 +13,11 @@ trait ScalaStepDefinition extends StepDefinition with AbstractGlueDefinition {
1413

1514
override val location: StackTraceElement = stepDetails.frame
1615

17-
val parametersInfo: JList[ParameterInfo] = fromTypes(stepDetails.types)
16+
override val parameterInfos: JList[ParameterInfo] = fromTypes(stepDetails.types)
1817

19-
private def fromTypes(types: Array[Type]): JList[ParameterInfo] = {
18+
private def fromTypes(types: Seq[Manifest[_]]): JList[ParameterInfo] = {
2019
types
20+
.map(ScalaTypeHelper.asJavaType)
2121
.map(new ScalaTypeResolver(_))
2222
.map(new ScalaParameterInfo(_))
2323
.toList
@@ -34,8 +34,6 @@ trait ScalaStepDefinition extends StepDefinition with AbstractGlueDefinition {
3434

3535
override def getPattern: String = stepDetails.pattern
3636

37-
override def parameterInfos(): JList[ParameterInfo] = parametersInfo
38-
3937
// Easier to just print out fileName and lineNumber
4038
override def getLocation(): String = stepDetails.frame.getFileName + ":" + stepDetails.frame.getLineNumber
4139

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.cucumber.scala
22

3-
import java.lang.reflect.Type
4-
53
/**
64
* Implementation of step definition for scala.
75
*
@@ -15,5 +13,5 @@ import java.lang.reflect.Type
1513
case class ScalaStepDetails(frame: StackTraceElement,
1614
name: String,
1715
pattern: String,
18-
types: Array[Type],
16+
types: Seq[Manifest[_]],
1917
body: List[Any] => Any)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.cucumber.scala
2+
3+
import java.lang.reflect.{ParameterizedType, Type}
4+
5+
object ScalaTypeHelper {
6+
7+
def asJavaType(m: Manifest[_]): Type = {
8+
if (m.typeArguments.isEmpty) {
9+
m.runtimeClass
10+
} else {
11+
new ScalaParameterizedType(m)
12+
}
13+
}
14+
15+
}
16+
17+
class ScalaParameterizedType(manifest: Manifest[_]) extends ParameterizedType {
18+
19+
override def getActualTypeArguments: Array[Type] = manifest.typeArguments.map(ScalaTypeHelper.asJavaType).toArray
20+
21+
override def getRawType: Type = manifest.runtimeClass
22+
23+
override def getOwnerType: Type = null
24+
25+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
Feature: As Cucumber Scala, I want to parse DataTables properly
2+
3+
Scenario: As datatable
4+
Given the following table as DataTable
5+
| key1 | key2 | key3 |
6+
| val11 | val12 | val13 |
7+
| val21 | val22 | val23 |
8+
| val31 | val32 | val33 |
9+
10+
Scenario: As List of Map
11+
Given the following table as List of Map
12+
| key1 | key2 | key3 |
13+
| val11 | val12 | val13 |
14+
| val21 | val22 | val23 |
15+
| val31 | val32 | val33 |
16+
17+
Scenario: As List of List
18+
Given the following table as List of List
19+
| val11 | val12 | val13 |
20+
| val21 | val22 | val23 |
21+
| val31 | val32 | val33 |
22+
23+
Scenario: As Map of Map
24+
Given the following table as Map of Map
25+
| | key1 | key2 | key3 |
26+
| row1 | val11 | val12 | val13 |
27+
| row2 | val21 | val22 | val23 |
28+
| row3 | val31 | val32 | val33 |
29+
30+
Scenario: As Map of List
31+
Given the following table as Map of List
32+
| row1 | val11 | val12 | val13 |
33+
| row2 | val21 | val22 | val23 |
34+
| row3 | val31 | val32 | val33 |
35+
36+
Scenario: As Map
37+
Given the following table as Map
38+
| row1 | val11 |
39+
| row2 | val21 |
40+
| row3 | val31 |
41+
42+
Scenario: As List
43+
Given the following table as List
44+
| val11 |
45+
| val21 |
46+
| val31 |

scala/sources/src/test/scala/tests/datatables/DatatablesSteps.scala renamed to scala/sources/src/test/scala/tests/datatables/DataTableTypeSteps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import io.cucumber.datatable.DataTable
88
import scala.jdk.CollectionConverters._
99

1010

11-
class DatatablesSteps extends ScalaDsl with EN {
11+
class DataTableTypeSteps extends ScalaDsl with EN {
1212

1313
case class GroupOfAuthor(authors: Seq[Author])
1414

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package tests.datatables
2+
3+
import java.util.{List => JavaList, Map => JavaMap}
4+
5+
import io.cucumber.datatable.DataTable
6+
import io.cucumber.scala.{EN, ScalaDsl}
7+
8+
import scala.jdk.CollectionConverters._
9+
10+
class DatatableSteps extends ScalaDsl with EN {
11+
12+
Given("the following table as DataTable") { (table: DataTable) =>
13+
val data: Seq[Map[String, String]] = table.asMaps().asScala.map(_.asScala.toMap).toSeq
14+
val expected = Seq(
15+
Map("key1" -> "val11", "key2" -> "val12", "key3" -> "val13"),
16+
Map("key1" -> "val21", "key2" -> "val22", "key3" -> "val23"),
17+
Map("key1" -> "val31", "key2" -> "val32", "key3" -> "val33")
18+
)
19+
assert(data == expected)
20+
}
21+
22+
Given("the following table as List of Map") { (table: JavaList[JavaMap[String, String]]) =>
23+
val data: Seq[Map[String, String]] = table.asScala.map(_.asScala.toMap).toSeq
24+
val expected = Seq(
25+
Map("key1" -> "val11", "key2" -> "val12", "key3" -> "val13"),
26+
Map("key1" -> "val21", "key2" -> "val22", "key3" -> "val23"),
27+
Map("key1" -> "val31", "key2" -> "val32", "key3" -> "val33")
28+
)
29+
assert(data == expected)
30+
}
31+
32+
Given("the following table as List of List") { (table: JavaList[JavaList[String]]) =>
33+
val data: Seq[Seq[String]] = table.asScala.map(_.asScala.toSeq).toSeq
34+
val expected = Seq(
35+
Seq("val11", "val12", "val13"),
36+
Seq("val21", "val22", "val23"),
37+
Seq("val31", "val32", "val33")
38+
)
39+
assert(data == expected)
40+
}
41+
42+
Given("the following table as Map of Map") { (table: JavaMap[String, JavaMap[String, String]]) =>
43+
val data: Map[String, Map[String, String]] = table.asScala.map { case (k, v) => k -> v.asScala.toMap }.toMap
44+
val expected = Map(
45+
"row1" -> Map("key1" -> "val11", "key2" -> "val12", "key3" -> "val13"),
46+
"row2" -> Map("key1" -> "val21", "key2" -> "val22", "key3" -> "val23"),
47+
"row3" -> Map("key1" -> "val31", "key2" -> "val32", "key3" -> "val33")
48+
)
49+
assert(data == expected)
50+
}
51+
52+
Given("the following table as Map of List") { (table: JavaMap[String, JavaList[String]]) =>
53+
val data: Map[String, Seq[String]] = table.asScala.map { case (k, v) => k -> v.asScala.toSeq }.toMap
54+
val expected = Map(
55+
"row1" -> Seq("val11", "val12", "val13"),
56+
"row2" -> Seq("val21", "val22", "val23"),
57+
"row3" -> Seq("val31", "val32", "val33")
58+
)
59+
assert(data == expected)
60+
}
61+
62+
Given("the following table as Map") { (table: JavaMap[String, String]) =>
63+
val data: Map[String, String] = table.asScala.toMap
64+
val expected = Map(
65+
"row1" -> "val11",
66+
"row2" -> "val21",
67+
"row3" -> "val31"
68+
)
69+
assert(data == expected)
70+
}
71+
72+
Given("the following table as List") { (table: JavaList[String]) =>
73+
val data: Seq[String] = table.asScala.toSeq
74+
val expected = Seq(
75+
"val11",
76+
"val21",
77+
"val31"
78+
)
79+
assert(data == expected)
80+
}
81+
82+
}

0 commit comments

Comments
 (0)