Skip to content

Commit 0983955

Browse files
authored
Merge pull request #40 from cucumber/hooks-no-parameters
Allow to define hooks with by name body
2 parents ff6e864 + 8812e9f commit 0983955

18 files changed

+1873
-1338
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ See also the [CHANGELOG](https://github.com/cucumber/cucumber-jvm/blob/master/CH
1717
- See [Transformers](docs/transformers.md)
1818
- [Transformers] Add optional `JacksonDefaultDataTableEntryTransformer` ([#31](https://github.com/cucumber/cucumber-jvm-scala/issues/31) Gaël Jourdan-Weil)
1919
- See [here](docs/default_jackson_datatable_transformer.md)
20+
- [Scala DSL] Support hooks with by name body ([#26](https://github.com/cucumber/cucumber-jvm-scala/issues/26) Gaël Jourdan-Weil)
2021

2122
### Changed
2223

docs/hooks.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ Scenario hooks run for every scenario.
1717
Before { scenario : Scenario =>
1818
// Do something before each scenario
1919
}
20+
21+
// Or:
22+
Before {
23+
// Do something before each scenario
24+
}
2025
```
2126

2227
### After
@@ -27,6 +32,11 @@ Before { scenario : Scenario =>
2732
After { scenario : Scenario =>
2833
// Do something after each scenario
2934
}
35+
36+
// Or:
37+
After {
38+
// Do something after each scenario
39+
}
3040
```
3141

3242
## Step hooks
@@ -39,6 +49,11 @@ Step hooks invoked before and after a step.
3949
BeforeStep { scenario : Scenario =>
4050
// Do something before step
4151
}
52+
53+
// Or:
54+
BeforeStep {
55+
// Do something before step
56+
}
4257
```
4358

4459
### AfterStep
@@ -47,14 +62,19 @@ BeforeStep { scenario : Scenario =>
4762
AfterStep { scenario : Scenario =>
4863
// Do something after step
4964
}
65+
66+
// Or:
67+
AfterStep {
68+
// Do something after step
69+
}
5070
```
5171

5272
## Conditional hooks
5373

5474
Hooks can be conditionally selected for execution based on the tags of the scenario.
5575

5676
```scala
57-
Before("@browser and not @headless") { _ =>
77+
Before("@browser and not @headless") {
5878
// Do something before each scenario with tag @browser but not @headless
5979
}
6080
```
@@ -64,11 +84,11 @@ Before("@browser and not @headless") { _ =>
6484
You can define an order between multiple hooks.
6585

6686
```scala
67-
Before(10) { _ =>
87+
Before(10) {
6888
// Do something before each scenario
6989
}
7090

71-
Before(20) { _ =>
91+
Before(20) {
7292
// Do something before each scenario
7393
}
7494
```
@@ -79,7 +99,7 @@ The **default order is 1000**.
7999

80100
You mix up conditional and order hooks with following syntax:
81101
```scala
82-
Before("@browser and not @headless", 10) { _ =>
102+
Before("@browser and not @headless", 10) {
83103
// Do something before each scenario
84104
}
85105
```

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package io.cucumber.scala
55
*/
66
object Aliases {
77

8-
type HookBody = Scenario => Unit
8+
type HookDefinitionBody = Scenario => Unit
99

1010
type StepDefinitionBody = () => Unit
1111

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

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.cucumber.scala
22

33
import java.lang.reflect.{ParameterizedType, Type}
44

5-
import io.cucumber.scala.Aliases.{DefaultDataTableCellTransformerBody, DefaultDataTableEntryTransformerBody, DefaultParameterTransformerBody, DocStringDefinitionBody, HookBody}
5+
import io.cucumber.scala.Aliases._
66

77
import scala.reflect.ClassTag
88

@@ -28,70 +28,72 @@ trait ScalaDsl extends BaseScalaDsl with StepDsl with HookDsl with DataTableType
2828

2929
private[scala] trait HookDsl extends BaseScalaDsl {
3030

31-
// TODO support Before/After with no parameter
31+
private sealed trait HookType
3232

33-
def Before(body: HookBody): Unit = {
34-
Before(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)(body)
35-
}
33+
private object HookType {
3634

37-
def Before(tagExpression: String)(body: HookBody): Unit = {
38-
Before(tagExpression, DEFAULT_BEFORE_ORDER)(body)
39-
}
35+
case object BEFORE extends HookType
4036

41-
def Before(order: Int)(body: HookBody): Unit = {
42-
Before(EMPTY_TAG_EXPRESSION, order)(body)
43-
}
37+
case object BEFORE_STEP extends HookType
4438

45-
def Before(tagExpression: String, order: Int)(body: HookBody): Unit = {
46-
registry.beforeHooks += ScalaHookDetails(tagExpression, order, body)
47-
}
39+
case object AFTER extends HookType
4840

49-
def BeforeStep(body: HookBody): Unit = {
50-
BeforeStep(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)(body)
51-
}
41+
case object AFTER_STEP extends HookType
5242

53-
def BeforeStep(tagExpression: String)(body: HookBody): Unit = {
54-
BeforeStep(tagExpression, DEFAULT_BEFORE_ORDER)(body)
5543
}
5644

57-
def BeforeStep(order: Int)(body: HookBody): Unit = {
58-
BeforeStep(EMPTY_TAG_EXPRESSION, order)(body)
59-
}
45+
def Before: HookBody = Before(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)
6046

61-
def BeforeStep(tagExpression: String, order: Int)(body: HookBody): Unit = {
62-
registry.beforeStepHooks += ScalaHookDetails(tagExpression, order, body)
63-
}
47+
def Before(tagExpression: String): HookBody = Before(tagExpression, DEFAULT_BEFORE_ORDER)
6448

65-
def After(body: HookBody): Unit = {
66-
After(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)(body)
67-
}
49+
def Before(order: Int): HookBody = Before(EMPTY_TAG_EXPRESSION, order)
6850

69-
def After(tagExpression: String)(body: HookBody): Unit = {
70-
After(tagExpression, DEFAULT_AFTER_ORDER)(body)
71-
}
51+
def Before(tagExpression: String, order: Int): HookBody = new HookBody(HookType.BEFORE, tagExpression, order)
7252

73-
def After(order: Int)(body: HookBody): Unit = {
74-
After(EMPTY_TAG_EXPRESSION, order)(body)
75-
}
53+
def BeforeStep: HookBody = BeforeStep(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)
7654

77-
def After(tagExpression: String, order: Int)(body: HookBody): Unit = {
78-
registry.afterHooks += ScalaHookDetails(tagExpression, order, body)
79-
}
55+
def BeforeStep(tagExpression: String): HookBody = BeforeStep(tagExpression, DEFAULT_BEFORE_ORDER)
8056

81-
def AfterStep(body: HookBody): Unit = {
82-
AfterStep(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)(body)
83-
}
57+
def BeforeStep(order: Int): HookBody = BeforeStep(EMPTY_TAG_EXPRESSION, order)
8458

85-
def AfterStep(tagExpression: String)(body: HookBody): Unit = {
86-
AfterStep(tagExpression, DEFAULT_AFTER_ORDER)(body)
87-
}
59+
def BeforeStep(tagExpression: String, order: Int): HookBody = new HookBody(HookType.BEFORE_STEP, tagExpression, order)
8860

89-
def AfterStep(order: Int)(body: HookBody): Unit = {
90-
AfterStep(EMPTY_TAG_EXPRESSION, order)(body)
91-
}
61+
def After: HookBody = After(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)
62+
63+
def After(tagExpression: String): HookBody = After(tagExpression, DEFAULT_AFTER_ORDER)
64+
65+
def After(order: Int): HookBody = After(EMPTY_TAG_EXPRESSION, order)
66+
67+
def After(tagExpression: String, order: Int): HookBody = new HookBody(HookType.AFTER, tagExpression, order)
68+
69+
def AfterStep: HookBody = AfterStep(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)
70+
71+
def AfterStep(tagExpression: String): HookBody = AfterStep(tagExpression, DEFAULT_AFTER_ORDER)
72+
73+
def AfterStep(order: Int): HookBody = AfterStep(EMPTY_TAG_EXPRESSION, order)
74+
75+
def AfterStep(tagExpression: String, order: Int): HookBody = new HookBody(HookType.AFTER_STEP, tagExpression, order)
76+
77+
final class HookBody(hookType: HookType, tagExpression: String, order: Int) {
78+
79+
def apply(body: => Unit): Unit = {
80+
apply(_ => body)
81+
}
82+
83+
def apply(body: Scenario => Unit): Unit = {
84+
val details = ScalaHookDetails(tagExpression, order, body)
85+
hookType match {
86+
case HookType.BEFORE =>
87+
registry.beforeHooks += details
88+
case HookType.BEFORE_STEP =>
89+
registry.beforeStepHooks += details
90+
case HookType.AFTER =>
91+
registry.afterHooks += details
92+
case HookType.AFTER_STEP =>
93+
registry.afterStepHooks += details
94+
}
95+
}
9296

93-
def AfterStep(tagExpression: String, order: Int)(body: HookBody): Unit = {
94-
registry.afterStepHooks += ScalaHookDetails(tagExpression, order, body)
9597
}
9698

9799
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ trait ScalaHookDefinition extends HookDefinition with AbstractGlueDefinition {
99
override val location: StackTraceElement = new Exception().getStackTrace()(3)
1010

1111
override def execute(state: TestCaseState): Unit = {
12-
executeAsCucumber(hookDetails.body(new Scenario(state)))
12+
executeAsCucumber(hookDetails.body.apply(new Scenario(state)))
1313
}
1414

1515
override def getTagExpression: String = hookDetails.tagExpression
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package io.cucumber.scala
22

3-
import io.cucumber.scala.Aliases.HookBody
3+
import io.cucumber.scala.Aliases.HookDefinitionBody
44

5-
case class ScalaHookDetails(tagExpression: String, order: Int, body: HookBody)
5+
case class ScalaHookDetails(tagExpression: String, order: Int, body: HookDefinitionBody)

0 commit comments

Comments
 (0)