Skip to content

Commit e680ccc

Browse files
committed
Release 0.5.2
- Support for InputStream for reading template and environment files - Renamed Pre- and Post-hooks to PreStepHook and PostStepHook - revUp with multiple configs Signed-off-by: Gopal S Akshintala <[email protected]>
1 parent 2c10638 commit e680ccc

File tree

17 files changed

+153
-87
lines changed

17 files changed

+153
-87
lines changed

README.adoc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ endif::[]
1818
:pmtemplates: src/integrationTest/resources/pm-templates
1919
:imagesdir: docs/images
2020
:prewrap!:
21-
:revoman-version: 0.5.1
21+
:revoman-version: 0.5.2
2222

2323
'''
2424

@@ -200,9 +200,9 @@ Rundown(
200200
StepReport(
201201
step: Step,
202202
requestInfo: Either<RequestFailure, TxnInfo<Request>>? = null, // <1>
203-
preHookFailure: PreHookFailure? = null,
203+
preStepHookFailure: PreStepHookFailure? = null,
204204
responseInfo: Either<ResponseFailure, TxnInfo<Response>>? = null,
205-
postHookFailure: PostHookFailure? = null,
205+
postStepHookFailure: PostStepHookFailure? = null,
206206
envSnapshot: PostmanEnvironment<Any?> // <2>
207207
)
208208
----
@@ -304,7 +304,7 @@ assertThat(pqRundown.mutableEnv)
304304
<7> <<Execution Control>>
305305
<8> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Request Config>>
306306
<9> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Response Config>>
307-
<10> <<#_pre_and_post_hooks>>
307+
<10> <<#_pre_and_post_step_hooks>>
308308
<11> <<Response Validations>>
309309
<12> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Global Custom Type Adapters>>
310310
<13> Ignore Java cert issues when firing HTTP calls
@@ -327,7 +327,7 @@ include::{integrationtestdir}/com/salesforce/revoman/integration/core/pq/PQE2EWi
327327
<7> <<Execution Control>>
328328
<8> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Request Config>>
329329
<9> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Response Config>>
330-
<10> <<#_pre_and_post_hooks>>
330+
<10> <<#_pre_and_post_step_hooks>>
331331
<11> <<Response Validations>>
332332
<12> <<#_type_safety_with_flexible_json_pojo_marshallingserialization_and_unmarshallingdeserialization, Global Custom Type Adapters>>
333333
<13> Ignore Java cert issues when firing HTTP calls
@@ -406,8 +406,8 @@ The configuration offers methods through which the execution strategy can be con
406406
* `runOnlySteps`, `skipSteps` — All these accept a `predicate` of type `ExeStepPick`, which is invoked passing the current `Step` instance to decide whether to execute or skip a step.
407407
** There are some `ExeStepPick` predicates bundled with ReṼoman under `ExeStepPick.PickUtils` e.g `withName`, `inFolder` etc. You can write a custom predicate of your own too.
408408

409-
[#_pre_and_post_hooks]
410-
=== Pre- and Post-Hooks
409+
[#_pre_and_post_step_hooks]
410+
=== Pre- and Post-Step Hooks
411411

412412
A hook lets you fiddle with the execution by plugging in your code before or after a Step execution.
413413

@@ -491,7 +491,7 @@ CAUTION: The recommendation is not to add too much code in <<Pre-req and Post-re
491491
=== Mutable Environment
492492

493493
* Environment is the only mutable-shared state across step executions, which can be used for data passing between the consumer and the library.
494-
* This can be mutated (set key-value pairs) through <<Pre-req and Post-res scripts>> (using `pm.environment.set()`) and <<#_pre_and_post_hooks,Pre-/Post-Hooks>> (using the reference `rundown.mutableEnv`) during execution.
494+
* This can be mutated (set key-value pairs) through <<Pre-req and Post-res scripts>> (using `pm.environment.set()`) and <<#_pre_and_post_step_hooks,Pre-/Post-Hooks>> (using the reference `rundown.mutableEnv`) during execution.
495495

496496
==== Read Mutable Environment as Postman Environment JSON format
497497

@@ -507,7 +507,8 @@ Each StepReport also has a `pmEnvSnapshot` to assert if a step has executed as e
507507

508508
* You don't have to squash all your steps into one mega collection. Instead, you can break them into easy-to-manage modular collections. `ReVoman.revUp()` accepts a list of collection paths through `templatePaths()`
509509
* But that doesn't mean you have to execute all these templates in one-go. You can make multiple `ReVoman.revUp()` calls for different collections.
510-
* If you wish to compose these executions, you can do so by adding the previous execution's `mutableEnv` to the current execution using the `dynamicEnvironment` parameter. This also comes in handy when you wish to execute a common step (e.g. `UserSetup`) inside a Test setup method and use that environment for all the tests.
510+
* If you wish to compose these executions in a specific order, you can use the `revUp` overload which accepts a vararg `Kick` configs.
511+
** You can also achieve the same yourself, by adding the previous execution's `mutableEnv` to the current execution using the `dynamicEnvironment` parameter. This also comes in handy when you wish to execute a common step (e.g. `UserSetup`) inside a Test setup method and use that environment for all the tests.
511512

512513
=== Custom Dynamic variables
513514

@@ -567,13 +568,13 @@ The future looks bright with multiple impactful features in the pipeline:
567568

568569
=== How to Debug a step in the middle of an Execution?
569570

570-
* You can add a <<#_pre_and_post_hooks,pre-hook>> to the Step you are interested and add a debug point inside that. This gets hit before ReṼoman fires the request in that Step
571+
* You can add a <<#_pre_and_post_step_hooks,pre-hook>> to the Step you are interested and add a debug point inside that. This gets hit before ReṼoman fires the request in that Step
571572
* You can get more adventurous by attaching revoman jar sources and directly adding conditional debug points inside this library source-code. You can search for logs in the source-code that indicate key operations to add conditional debug points with conditions like StepName etc.
572573

573574
=== Is there a way to add Metadata to a Postman collection Step?
574575

575576
* You can add key-value pairs to a Step's HTTP Headers section (e.g., `ignoreHTTPStatusUnsuccessful=true`).
576-
* You can use this information in <<#_step_picks,Step Picks>> or <<#_pre_and_post_hooks>> to identify a particular step to execute any conditional logic
577+
* You can use this information in <<#_step_picks,Step Picks>> or <<#_pre_and_post_step_hooks>> to identify a particular step to execute any conditional logic
577578

578579
=== Do I need to migrate all my existing TestUtils to Postman Collections?
579580

buildSrc/src/main/kotlin/Config.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
* ************************************************************************************************
77
*/
88
const val GROUP_ID = "com.salesforce.revoman"
9-
const val VERSION = "0.5.1"
9+
const val VERSION = "0.5.2"
1010
const val ARTIFACT_ID = "revoman"
1111
const val STAGING_PROFILE_ID = "1ea0a23e61ba7d"

src/integrationTest/java/com/salesforce/revoman/integration/pokemon/PokemonTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import static org.mockito.Mockito.times;
2020

2121
import com.salesforce.revoman.ReVoman;
22-
import com.salesforce.revoman.input.config.HookConfig.Hook.PostHook;
23-
import com.salesforce.revoman.input.config.HookConfig.Hook.PreHook;
22+
import com.salesforce.revoman.input.config.HookConfig.StepHook.PostStepHook;
23+
import com.salesforce.revoman.input.config.HookConfig.StepHook.PreStepHook;
2424
import com.salesforce.revoman.input.config.Kick;
2525
import com.salesforce.revoman.output.Rundown;
2626
import com.salesforce.revoman.output.report.Step;
@@ -54,7 +54,7 @@ void pokemon() {
5454
//noinspection Convert2Lambda
5555
final var preLogHook =
5656
Mockito.spy(
57-
new PreHook() {
57+
new PreStepHook() {
5858
@Override
5959
public void accept(
6060
@NotNull Step currentStep,
@@ -66,7 +66,7 @@ public void accept(
6666
//noinspection Convert2Lambda
6767
final var postLogHook =
6868
Mockito.spy(
69-
new PostHook() {
69+
new PostStepHook() {
7070
@Override
7171
public void accept(@NotNull StepReport stepReport, @NotNull Rundown rundown) {
7272
LOGGER.info("Picked `postLogHook` after stepName: {}", stepReport.step.displayName);
@@ -75,7 +75,7 @@ public void accept(@NotNull StepReport stepReport, @NotNull Rundown rundown) {
7575
//noinspection Convert2Lambda
7676
final var preHook =
7777
Mockito.spy(
78-
new PreHook() {
78+
new PreStepHook() {
7979
@Override
8080
public void accept(
8181
@NotNull Step currentStep,
@@ -87,7 +87,7 @@ public void accept(
8787
//noinspection Convert2Lambda
8888
final var postHook =
8989
Mockito.spy(
90-
new PostHook() {
90+
new PostStepHook() {
9191
@Override
9292
public void accept(@NotNull StepReport ignore2, @NotNull Rundown rundown) {
9393
assertThat(rundown.mutableEnv).containsEntry("limit", String.valueOf(newLimit));
@@ -97,7 +97,7 @@ public void accept(@NotNull StepReport ignore2, @NotNull Rundown rundown) {
9797
//noinspection Convert2Lambda
9898
final var postHookAfterURIPath =
9999
Mockito.spy(
100-
new PostHook() {
100+
new PostStepHook() {
101101
@Override
102102
public void accept(@NotNull StepReport stepReport, @NotNull Rundown ignore) {
103103
LOGGER.info(

src/main/kotlin/com/salesforce/revoman/ReVoman.kt

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import arrow.core.Either.Left
1111
import arrow.core.Either.Right
1212
import arrow.core.flatMap
1313
import arrow.core.merge
14+
import com.salesforce.revoman.input.PostExeHook
1415
import com.salesforce.revoman.input.bufferFileInResources
16+
import com.salesforce.revoman.input.bufferInputStream
1517
import com.salesforce.revoman.input.config.Kick
1618
import com.salesforce.revoman.internal.exe.deepFlattenItems
1719
import com.salesforce.revoman.internal.exe.executePostResJS
@@ -43,12 +45,20 @@ import org.http4k.core.Request
4345
import org.http4k.format.ConfigurableMoshi
4446

4547
object ReVoman {
46-
4748
@JvmStatic
4849
@JvmOverloads
4950
fun revUp(
50-
dynamicEnvironment: Map<String, String> = mapOf<String, String>(),
5151
vararg kicks: Kick,
52+
postExeHook: PostExeHook = PostExeHook { _, _ -> },
53+
dynamicEnvironment: Map<String, String> = emptyMap(),
54+
): List<Rundown> = revUp(kicks.toList(), postExeHook, dynamicEnvironment)
55+
56+
@JvmStatic
57+
@JvmOverloads
58+
fun revUp(
59+
kicks: List<Kick>,
60+
postExeHook: PostExeHook = PostExeHook { _, _ -> },
61+
dynamicEnvironment: Map<String, String> = emptyMap(),
5262
): List<Rundown> =
5363
kicks
5464
.fold(dynamicEnvironment to listOf<Rundown>()) { (accumulatedMutableEnv, rundowns), kick ->
@@ -59,19 +69,23 @@ object ReVoman {
5969
accumulatedMutableEnv,
6070
)
6171
)
62-
rundown.mutableEnv.mutableEnvCopyWithValuesOfType<String>() to (rundowns + rundown)
72+
val accumulatedRundowns = rundowns + rundown
73+
postExeHook.accept(rundown, accumulatedRundowns)
74+
rundown.mutableEnv.mutableEnvCopyWithValuesOfType<String>() to accumulatedRundowns
6375
}
6476
.second
6577

6678
@JvmStatic
6779
@OptIn(ExperimentalStdlibApi::class)
6880
fun revUp(kick: Kick): Rundown {
6981
val pmTemplateAdapter = Moshi.Builder().build().adapter<Template>()
82+
val templateBuffers =
83+
kick.templatePaths().map { bufferFileInResources(it) } +
84+
kick.templateInputStreams().map { bufferInputStream(it) }
7085
val pmStepsDeepFlattened =
71-
kick
72-
.templatePaths()
86+
templateBuffers
7387
.asSequence()
74-
.mapNotNull { pmTemplateAdapter.fromJson(bufferFileInResources(it)) }
88+
.mapNotNull { pmTemplateAdapter.fromJson(it) }
7589
.flatMap { (pmSteps, authFromRoot) ->
7690
deepFlattenItems(
7791
pmSteps.map { item ->
@@ -92,7 +106,12 @@ object ReVoman {
92106
kick.customTypeAdaptersFromRequestConfig() + kick.customTypeAdaptersFromResponseConfig(),
93107
kick.globalSkipTypes(),
94108
)
95-
val environment = mergeEnvs(kick.environmentPaths(), kick.dynamicEnvironmentsFlattened())
109+
val environment =
110+
mergeEnvs(
111+
kick.environmentPaths(),
112+
kick.environmentInputStreams(),
113+
kick.dynamicEnvironmentsFlattened(),
114+
)
96115
val pm =
97116
PostmanSDK(
98117
moshiReVoman,
@@ -149,7 +168,10 @@ object ReVoman {
149168
.flatMap { requestInfo: TxnInfo<Request> -> // --------### PRE-HOOKS ###--------
150169
preHookExe(step, kick, requestInfo, pm)?.let {
151170
Left(
152-
preStepReport.copy(requestInfo = Right(requestInfo).toVavr(), preHookFailure = it)
171+
preStepReport.copy(
172+
requestInfo = Right(requestInfo).toVavr(),
173+
preStepHookFailure = it,
174+
)
153175
)
154176
} ?: Right(preStepReport.copy(requestInfo = Right(requestInfo).toVavr()))
155177
}
@@ -183,7 +205,7 @@ object ReVoman {
183205
.map { sr: StepReport -> // --------### POST-HOOKS ###--------
184206
pm.currentStepReport = sr
185207
pm.rundown = pm.rundown.copy(stepReports = pm.rundown.stepReports + sr)
186-
sr.copy(postHookFailure = postHookExe(kick, pm))
208+
sr.copy(postStepHookFailure = postHookExe(kick, pm))
187209
}
188210
.merge()
189211
.copy(

src/main/kotlin/com/salesforce/revoman/input/FileUtils.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package com.salesforce.revoman.input
1111

1212
import java.io.File
13+
import java.io.InputStream
1314
import okio.BufferedSource
1415
import okio.FileSystem
1516
import okio.Path.Companion.toPath
@@ -22,6 +23,11 @@ fun bufferFileInResources(fileRelativePath: String): BufferedSource =
2223
fun readFileInResourcesToString(fileRelativePath: String): String =
2324
bufferFileInResources(fileRelativePath).readUtf8()
2425

26+
fun bufferInputStream(inputStream: InputStream): BufferedSource = inputStream.source().buffer()
27+
28+
fun readInputStreamToString(inputStream: InputStream): String =
29+
bufferInputStream(inputStream).readUtf8()
30+
2531
fun bufferFile(file: File): BufferedSource = file.source().buffer()
2632

2733
fun readFileToString(file: File): String = bufferFile(file).readUtf8()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* ************************************************************************************************
3+
* Copyright (c) 2023, Salesforce, Inc. All rights reserved. SPDX-License-Identifier: Apache License
4+
* Version 2.0 For full license text, see the LICENSE file in the repo root or
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
* ************************************************************************************************
7+
*/
8+
package com.salesforce.revoman.input
9+
10+
import com.salesforce.revoman.output.Rundown
11+
12+
fun interface PostExeHook {
13+
@Throws(Throwable::class) fun accept(currentRundown: Rundown, rundowns: List<Rundown>)
14+
}

src/main/kotlin/com/salesforce/revoman/input/config/HookConfig.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
*/
88
package com.salesforce.revoman.input.config
99

10-
import com.salesforce.revoman.input.config.HookConfig.Hook.PostHook
11-
import com.salesforce.revoman.input.config.HookConfig.Hook.PreHook
10+
import com.salesforce.revoman.input.config.HookConfig.StepHook.PostStepHook
11+
import com.salesforce.revoman.input.config.HookConfig.StepHook.PreStepHook
1212
import com.salesforce.revoman.input.config.StepPick.PostTxnStepPick
1313
import com.salesforce.revoman.input.config.StepPick.PreTxnStepPick
1414
import com.salesforce.revoman.output.Rundown
@@ -18,21 +18,22 @@ import com.salesforce.revoman.output.report.TxnInfo
1818
import org.http4k.core.Request
1919

2020
@ExposedCopyVisibility
21-
data class HookConfig private constructor(val pick: StepPick, val hook: Hook) {
22-
sealed interface Hook {
23-
fun interface PreHook : Hook {
21+
data class HookConfig private constructor(val pick: StepPick, val stepHook: StepHook) {
22+
sealed interface StepHook {
23+
fun interface PreStepHook : StepHook {
2424
@Throws(Throwable::class)
2525
fun accept(currentStep: Step, requestInfo: TxnInfo<Request>, rundown: Rundown)
2626
}
2727

28-
fun interface PostHook : Hook {
28+
fun interface PostStepHook : StepHook {
2929
@Throws(Throwable::class) fun accept(currentStepReport: StepReport, rundown: Rundown)
3030
}
3131
}
3232

3333
companion object {
34-
@JvmStatic fun pre(pick: PreTxnStepPick, hook: PreHook): HookConfig = HookConfig(pick, hook)
34+
@JvmStatic fun pre(pick: PreTxnStepPick, hook: PreStepHook): HookConfig = HookConfig(pick, hook)
3535

36-
@JvmStatic fun post(pick: PostTxnStepPick, hook: PostHook): HookConfig = HookConfig(pick, hook)
36+
@JvmStatic
37+
fun post(pick: PostTxnStepPick, hook: PostStepHook): HookConfig = HookConfig(pick, hook)
3738
}
3839
}

src/main/kotlin/com/salesforce/revoman/input/config/KickDef.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import com.salesforce.revoman.output.report.StepReport
1616
import com.squareup.moshi.JsonAdapter
1717
import com.squareup.moshi.JsonAdapter.Factory
1818
import io.vavr.control.Either
19+
import java.io.InputStream
1920
import java.lang.reflect.Type
2021
import java.util.Collections.disjoint
2122
import org.immutables.value.Value
@@ -24,11 +25,16 @@ import org.immutables.value.Value.Style.ImplementationVisibility.PUBLIC
2425
@Config
2526
@Value.Immutable
2627
internal interface KickDef {
27-
// * NOTE 29/10/23 gopala.akshintala: `List` coz it allows adding a template twice
28+
// * NOTE 29/10/23 gopala.akshintala: `List` coz it allows adding a template twice,
29+
// as there can be use-cases to execute the same template twice
2830
fun templatePaths(): List<String>
2931

32+
fun templateInputStreams(): List<InputStream>
33+
3034
fun environmentPaths(): Set<String>
3135

36+
fun environmentInputStreams(): List<InputStream>
37+
3238
fun dynamicEnvironments(): List<Map<String, String>>
3339

3440
fun nodeModulesRelativePath(): String?

src/main/kotlin/com/salesforce/revoman/internal/exe/PostHook.kt renamed to src/main/kotlin/com/salesforce/revoman/internal/exe/PostStepHook.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@
88
package com.salesforce.revoman.internal.exe
99

1010
import com.salesforce.revoman.input.config.HookConfig
11-
import com.salesforce.revoman.input.config.HookConfig.Hook.PostHook
11+
import com.salesforce.revoman.input.config.HookConfig.StepHook.PostStepHook
1212
import com.salesforce.revoman.input.config.Kick
1313
import com.salesforce.revoman.input.config.StepPick.PostTxnStepPick
1414
import com.salesforce.revoman.internal.postman.PostmanSDK
15-
import com.salesforce.revoman.output.ExeType.POST_HOOK
15+
import com.salesforce.revoman.output.ExeType.POST_STEP_HOOK
1616
import com.salesforce.revoman.output.Rundown
1717
import com.salesforce.revoman.output.report.StepReport
18-
import com.salesforce.revoman.output.report.failure.HookFailure.PostHookFailure
18+
import com.salesforce.revoman.output.report.failure.HookFailure.PostStepHookFailure
1919
import io.github.oshai.kotlinlogging.KotlinLogging
2020

21-
internal fun postHookExe(kick: Kick, pm: PostmanSDK): PostHookFailure? =
21+
internal fun postHookExe(kick: Kick, pm: PostmanSDK): PostStepHookFailure? =
2222
pickPostHooks(kick.postHooks(), pm.currentStepReport, pm.rundown)
2323
.asSequence()
2424
.map { postHook ->
25-
runChecked(pm.currentStepReport.step, POST_HOOK) {
25+
runChecked(pm.currentStepReport.step, POST_STEP_HOOK) {
2626
postHook.accept(pm.currentStepReport, pm.rundown)
2727
}
28-
.mapLeft { PostHookFailure(it) }
28+
.mapLeft { PostStepHookFailure(it) }
2929
}
3030
.firstOrNull { it.isLeft() }
3131
?.leftOrNull()
@@ -34,11 +34,11 @@ private fun pickPostHooks(
3434
postHooks: List<HookConfig>,
3535
currentStepReport: StepReport,
3636
rundown: Rundown,
37-
): List<PostHook> =
37+
): List<PostStepHook> =
3838
postHooks
3939
.asSequence()
4040
.filter { (it.pick as PostTxnStepPick).pick(currentStepReport, rundown) }
41-
.map { it.hook as PostHook }
41+
.map { it.stepHook as PostStepHook }
4242
.toList()
4343
.also {
4444
if (it.isNotEmpty()) {

0 commit comments

Comments
 (0)