Skip to content

Commit d2ca914

Browse files
committed
Release 0.5.3
- Move `postmanEnvJSONFormat()` to PostmanEnvironment - Add `getTypedObj()` to PostmanEnvironment - Add infix overload for `getTypedTxnObj()` in TxnInfo Signed-off-by: Gopal S Akshintala <gopala.akshintala@salesforce.com>
1 parent b5906e8 commit d2ca914

File tree

11 files changed

+162
-70
lines changed

11 files changed

+162
-70
lines changed

README.adoc

Lines changed: 29 additions & 17 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.2
21+
:revoman-version: 0.5.3
2222

2323
'''
2424

@@ -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_step_hooks>>
307+
<10> <<#_pre_step_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_step_hooks>>
330+
<10> <<#_pre_step_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,33 +406,45 @@ 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_step_hooks]
410-
=== Pre- and Post-Step Hooks
409+
[#_pre_step_and_post_step_hooks]
410+
=== Pre-Step 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

414414
[#_step_picks]
415-
You can pass a `PreTxnStepPick/PostTxnStepPick` which is a `Predicate` used to qualify a step for Pre-/Post-Hook respectively. ReṼoman comes bundled with some predicates under the namespace `PreTxnStepPick.PickUtils/PostTxnStepPick.PickUtils` e.g `beforeStepContainingURIPathOfAny`, `afterStepName` etc. If those don't fit your needs, you can write your own custom predicates too.
415+
You can pass a `PreTxnStepPick/PostTxnStepPick` which is a `Predicate` used
416+
to qualify a step for Pre-Step/Post-Step Hook respectively.
417+
ReṼoman comes
418+
bundled with some predicates under the namespace `PreTxnStepPick.PickUtils`/`PostTxnStepPick.PickUtils` e.g `beforeStepContainingURIPathOfAny`,
419+
`afterStepName` etc. If those don't fit your needs, you can write your own custom predicates like below:
420+
421+
[source,java,indent=0,options="nowrap"]
422+
----
423+
final var preTxnStepPick = (currentStep, requestInfo, rundown) -> LOGGER.info("Picked `preLogHook` before stepName: {}", currentStep)
424+
final var postTxnStepPick = (stepReport, rundown) -> LOGGER.info("Picked `postLogHook` after stepName: {}", stepReport.step.displayName)
425+
----
426+
427+
Add them to the config as below:
416428

417429
[source,java,indent=0,options="nowrap"]
418430
----
419431
.hooks(
420432
pre(
421-
PreTxnStepPick,
433+
preTxnStepPick,
422434
(currentStepName, requestInfo, rundown) -> {
423-
//...callback-code...
435+
//...code...
424436
}),
425437
post(
426-
PostTxnStepPick,
438+
postTxnStepPick,
427439
(currentStepName, rundown) -> {
428-
//...callback-code...
440+
//...code...
429441
})
430442
)
431443
----
432444

433445
You can do things like assertion on the rundown, response validation,
434-
or environment and even <<#_mutable_environment,mutate the environment>>,
435-
such that the execution of subsequent steps picks up those changes.
446+
or even <<#_mutable_environment,mutate the environment>> with a value you programmatically derived,
447+
such that the execution of later steps picks up those changes.
436448

437449
[#_plug_in_your_java_code_in_between_postman_execution]
438450
==== Plug-in your Java code in-between Postman execution
@@ -465,7 +477,7 @@ so the later steps can pick up value for `+{{xyzId}}+` variable from the environ
465477
npm install moment
466478
----
467479

468-
.Use inside pre- / post-script
480+
.Use inside pre-req and post-res scripts
469481
[source,javascript,indent=0,options="nowrap"]
470482
----
471483
var moment = require("moment");
@@ -491,12 +503,12 @@ CAUTION: The recommendation is not to add too much code in <<Pre-req and Post-re
491503
=== Mutable Environment
492504

493505
* 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_step_hooks,Pre-/Post-Hooks>> (using the reference `rundown.mutableEnv`) during execution.
506+
* This can be mutated (set key-value pairs) through <<Pre-req and Post-res scripts>> (using `pm.environment.set()`) and <<#_pre_step_and_post_step_hooks,Pre-/Post-Hooks>> (using the reference `rundown.mutableEnv`) during execution.
495507

496508
==== Read Mutable Environment as Postman Environment JSON format
497509

498510
You may want to troubleshoot manually with Postman using the Mutable environment built during the ReṼoman execution.
499-
`rundown.envInPostmanEnvJSONFormat()` converts the mutable environment into a Postman JSON format,
511+
`rundown.mutableEnv.postmanEnvJSONFormat()` converts the mutable environment into a Postman JSON format,
500512
so you can copy and import that conveniently into Postman.
501513

502514
==== `pmEnvSnapshot` in each StepReport
@@ -568,13 +580,13 @@ The future looks bright with multiple impactful features in the pipeline:
568580

569581
=== How to Debug a step in the middle of an Execution?
570582

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
583+
* You can add a <<#_pre_step_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
572584
* 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.
573585

574586
=== Is there a way to add Metadata to a Postman collection Step?
575587

576588
* You can add key-value pairs to a Step's HTTP Headers section (e.g., `ignoreHTTPStatusUnsuccessful=true`).
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
589+
* You can use this information in <<#_step_picks,Step Picks>> or <<#_pre_step_and_post_step_hooks>> to identify a particular step to execute any conditional logic
578590

579591
=== Do I need to migrate all my existing TestUtils to Postman Collections?
580592

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.2"
9+
const val VERSION = "0.5.3"
1010
const val ARTIFACT_ID = "revoman"
1111
const val STAGING_PROFILE_ID = "1ea0a23e61ba7d"

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

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ object ReVoman {
121121
)
122122
val stepNameToReport =
123123
executeStepsSerially(pmStepsDeepFlattened, kick, moshiReVoman, regexReplacer, pm)
124-
return Rundown(stepNameToReport, pm.environment, kick.haltOnFailureOfTypeExcept(), moshiReVoman)
124+
return Rundown(stepNameToReport, pm.environment, kick.haltOnFailureOfTypeExcept())
125125
}
126126

127127
private fun executeStepsSerially(
@@ -140,20 +140,11 @@ object ReVoman {
140140
logger.info { "***** Executing Step: $step *****" }
141141
val itemWithRegex = step.rawPMStep
142142
val preStepReport =
143-
StepReport(
144-
step,
145-
Right(TxnInfo(httpMsg = itemWithRegex.request.toHttpRequest())),
146-
moshiReVoman = moshiReVoman,
147-
)
143+
StepReport(step, Right(TxnInfo(httpMsg = itemWithRegex.request.toHttpRequest())))
148144
pm.info = Info(step.name)
149145
pm.currentStepReport = preStepReport
150146
pm.rundown =
151-
Rundown(
152-
stepReports + preStepReport,
153-
pm.environment,
154-
kick.haltOnFailureOfTypeExcept(),
155-
moshiReVoman,
156-
)
147+
Rundown(stepReports + preStepReport, pm.environment, kick.haltOnFailureOfTypeExcept())
157148
pm.environment.putAll(regexReplacer.replaceVariablesInEnv(pm))
158149
val currentStepReport: StepReport = // --------### PRE-REQ-JS ###--------
159150
executePreReqJS(step, itemWithRegex, pm)

src/main/kotlin/com/salesforce/revoman/internal/postman/PostmanSDK.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class PostmanSDK(
3131
val regexReplacer: RegexReplacer = RegexReplacer(),
3232
mutableEnv: MutableMap<String, Any?> = mutableMapOf(),
3333
) {
34-
@JvmField val environment: PostmanEnvironment<Any?> = PostmanEnvironment(mutableEnv)
34+
@JvmField val environment: PostmanEnvironment<Any?> = PostmanEnvironment(mutableEnv, moshiReVoman)
3535
lateinit var info: Info
3636
lateinit var request: Request
3737
lateinit var response: Response

src/main/kotlin/com/salesforce/revoman/output/Rundown.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,17 @@
88
package com.salesforce.revoman.output
99

1010
import com.salesforce.revoman.input.config.StepPick.PostTxnStepPick
11-
import com.salesforce.revoman.internal.postman.template.Environment.Companion.fromMap
1211
import com.salesforce.revoman.output.postman.PostmanEnvironment
1312
import com.salesforce.revoman.output.report.Folder.Companion.FOLDER_DELIMITER
1413
import com.salesforce.revoman.output.report.StepReport
15-
import org.http4k.format.ConfigurableMoshi
1614

1715
data class Rundown(
1816
@JvmField val stepReports: List<StepReport> = emptyList(),
1917
@JvmField val mutableEnv: PostmanEnvironment<Any?>,
2018
private val stepsToIgnoreForFailurePick: Map<ExeType, PostTxnStepPick>?,
21-
private val moshiReVoman: ConfigurableMoshi,
2219
) {
2320
@get:JvmName("immutableEnv") val immutableEnv: Map<String, Any?> by lazy { mutableEnv.toMap() }
2421

25-
@get:JvmName("envInPostmanEnvJSONFormat")
26-
val envInPostmanEnvJSONFormat: String by lazy {
27-
moshiReVoman.prettify(moshiReVoman.asFormatString(fromMap(mutableEnv, moshiReVoman)))
28-
}
29-
3022
@get:JvmName("firstUnsuccessfulStepReport")
3123
val firstUnsuccessfulStepReport: StepReport? by lazy {
3224
stepReports.firstOrNull { !it.isSuccessful }

src/main/kotlin/com/salesforce/revoman/output/postman/PostmanEnvironment.kt

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,29 @@
77
*/
88
package com.salesforce.revoman.output.postman
99

10+
import com.salesforce.revoman.internal.json.initMoshi
11+
import com.salesforce.revoman.internal.postman.template.Environment.Companion.fromMap
12+
import com.squareup.moshi.rawType
1013
import io.exoquery.pprint
1114
import io.github.oshai.kotlinlogging.KotlinLogging
12-
13-
/** This is more like a value class (wrapper) on mutableEnv providing some useful utilities */
14-
data class PostmanEnvironment<ValueT : Any?>(
15-
internal val mutableEnv: MutableMap<String, ValueT> = mutableMapOf()
15+
import java.lang.reflect.Type
16+
import org.http4k.format.ConfigurableMoshi
17+
18+
/** This is a Wrapper on `mutableEnv` map, providing some useful utilities */
19+
data class PostmanEnvironment<ValueT : Any?>
20+
@JvmOverloads
21+
constructor(
22+
val mutableEnv: MutableMap<String, ValueT> = mutableMapOf(),
23+
val moshiReVoman: ConfigurableMoshi = initMoshi(),
1624
) : MutableMap<String, ValueT> by mutableEnv {
1725

1826
@get:JvmName("immutableEnv") val immutableEnv: Map<String, ValueT> by lazy { mutableEnv.toMap() }
1927

28+
@get:JvmName("postmanEnvJSONFormat")
29+
val postmanEnvJSONFormat: String by lazy {
30+
moshiReVoman.prettify(moshiReVoman.asFormatString(fromMap(mutableEnv, moshiReVoman)))
31+
}
32+
2033
fun set(key: String, value: ValueT) {
2134
mutableEnv[key] = value
2235
logger.info { "pm environment variable set through JS - key: $key, value: ${pprint(value)}" }
@@ -41,7 +54,8 @@ data class PostmanEnvironment<ValueT : Any?>(
4154
mutableEnv
4255
.filter { type.isInstance(it.value) }
4356
.mapValues { type.cast(it.value) }
44-
.toMutableMap()
57+
.toMutableMap(),
58+
moshiReVoman,
4559
)
4660

4761
inline fun <reified T> mutableEnvCopyWithValuesOfType(): PostmanEnvironment<T> =
@@ -57,7 +71,8 @@ data class PostmanEnvironment<ValueT : Any?>(
5771
type.isInstance(it.value) && prefixes.any { prefix -> it.key.startsWith(prefix) }
5872
}
5973
.mapValues { type.cast(it.value) }
60-
.toMutableMap()
74+
.toMutableMap(),
75+
moshiReVoman,
6176
)
6277

6378
inline fun <reified T> mutableEnvCopyWithKeysStartingWith(
@@ -72,7 +87,8 @@ data class PostmanEnvironment<ValueT : Any?>(
7287
mutableEnv
7388
.filter { type.isInstance(it.value) && !whiteListKeys.contains(it.key) }
7489
.mapValues { type.cast(it.value) }
75-
.toMutableMap()
90+
.toMutableMap(),
91+
moshiReVoman,
7692
)
7793

7894
fun <T> mutableEnvCopyWithKeysNotStartingWith(
@@ -85,9 +101,27 @@ data class PostmanEnvironment<ValueT : Any?>(
85101
type.isInstance(it.value) && prefixes.all { suffix -> !it.key.startsWith(suffix) }
86102
}
87103
.mapValues { type.cast(it.value) }
88-
.toMutableMap()
104+
.toMutableMap(),
105+
moshiReVoman,
89106
)
90107

108+
fun <T : Any> getTypedObj(key: String, objType: Type): T? {
109+
val value = mutableEnv[key]
110+
return when {
111+
objType.rawType.isInstance(value) -> value
112+
else -> moshiReVoman.asA(moshiReVoman.asFormatString(value as Any), objType.rawType.kotlin)
113+
}
114+
as T
115+
}
116+
117+
inline fun <reified T : Any> getTypedObj(key: String): T? {
118+
val value = mutableEnv[key]
119+
return when {
120+
value is T -> value
121+
else -> moshiReVoman.asA(moshiReVoman.asFormatString(value as Any), T::class)
122+
}
123+
}
124+
91125
fun <T> mutableEnvCopyWithKeysEndingWith(
92126
type: Class<T>,
93127
vararg suffixes: String,
@@ -96,7 +130,8 @@ data class PostmanEnvironment<ValueT : Any?>(
96130
mutableEnv
97131
.filter { type.isInstance(it.value) && suffixes.any { suffix -> it.key.endsWith(suffix) } }
98132
.mapValues { type.cast(it.value) }
99-
.toMutableMap()
133+
.toMutableMap(),
134+
moshiReVoman,
100135
)
101136

102137
fun <T> mutableEnvCopyWithKeysNotEndingWith(
@@ -107,7 +142,8 @@ data class PostmanEnvironment<ValueT : Any?>(
107142
mutableEnv
108143
.filter { type.isInstance(it.value) && suffixes.all { suffix -> !it.key.endsWith(suffix) } }
109144
.mapValues { type.cast(it.value) }
110-
.toMutableMap()
145+
.toMutableMap(),
146+
moshiReVoman,
111147
)
112148

113149
fun <T> valuesForKeysStartingWith(type: Class<T>, prefix: String): Set<T> =

src/main/kotlin/com/salesforce/revoman/output/report/StepReport.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package com.salesforce.revoman.output.report
99

1010
import arrow.core.Either.Left
1111
import arrow.core.Either.Right
12-
import com.salesforce.revoman.internal.postman.template.Environment.Companion.fromMap
1312
import com.salesforce.revoman.output.ExeType
1413
import com.salesforce.revoman.output.postman.PostmanEnvironment
1514
import com.salesforce.revoman.output.report.TxnInfo.Companion.uriPathContains
@@ -24,7 +23,6 @@ import io.vavr.control.Either.left
2423
import io.vavr.control.Either.right
2524
import org.http4k.core.Request
2625
import org.http4k.core.Response
27-
import org.http4k.format.ConfigurableMoshi
2826

2927
data class StepReport
3028
internal constructor(
@@ -33,7 +31,6 @@ internal constructor(
3331
@JvmField val preStepHookFailure: PreStepHookFailure? = null,
3432
@JvmField val responseInfo: Either<out ResponseFailure, TxnInfo<Response>>? = null,
3533
@JvmField val postStepHookFailure: PostStepHookFailure? = null,
36-
private val moshiReVoman: ConfigurableMoshi,
3734
@JvmField val envSnapshot: PostmanEnvironment<Any?> = PostmanEnvironment(),
3835
) {
3936
internal constructor(
@@ -42,14 +39,12 @@ internal constructor(
4239
preStepHookFailure: PreStepHookFailure? = null,
4340
responseInfo: arrow.core.Either<ResponseFailure, TxnInfo<Response>>? = null,
4441
postStepHookFailure: PostStepHookFailure? = null,
45-
moshiReVoman: ConfigurableMoshi,
4642
) : this(
4743
step,
4844
requestInfo?.toVavr(),
4945
preStepHookFailure,
5046
responseInfo?.toVavr(),
5147
postStepHookFailure,
52-
moshiReVoman,
5348
)
5449

5550
@JvmField
@@ -66,11 +61,6 @@ internal constructor(
6661
val isHttpStatusSuccessful: Boolean =
6762
failure?.fold({ it !is PostStepHookFailure }, { true }) != true
6863

69-
@get:JvmName("envSnapShotInPostmanEnvJSONFormat")
70-
val envSnapShotInPostmanEnvJSONFormat: String by lazy {
71-
moshiReVoman.prettify(moshiReVoman.asFormatString(fromMap(envSnapshot, moshiReVoman)))
72-
}
73-
7464
companion object {
7565
private fun failure(
7666
requestInfo: Either<out ExeFailure, TxnInfo<Request>>? = null,

src/main/kotlin/com/salesforce/revoman/output/report/TxnInfo.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,29 @@ data class TxnInfo<HttpMsgT : HttpMessage>(
2626

2727
@JvmOverloads
2828
fun <T : Any> getTypedTxnObj(
29-
txObjType: Type,
29+
txnObjType: Type,
3030
customAdapters: List<Any> = emptyList(),
3131
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, JsonAdapter.Factory>>> =
3232
emptyMap(),
3333
typesToIgnore: Set<Class<out Any>> = emptySet(),
3434
): T? =
3535
jsonToPojo(
36-
txObjType,
36+
txnObjType,
37+
httpMsg.bodyString(),
38+
customAdapters,
39+
customAdaptersWithType,
40+
typesToIgnore,
41+
)
42+
43+
@JvmOverloads
44+
inline fun <reified T : Any> getTypedTxnObj(
45+
customAdapters: List<Any> = emptyList(),
46+
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, JsonAdapter.Factory>>> =
47+
emptyMap(),
48+
typesToIgnore: Set<Class<out Any>> = emptySet(),
49+
): T? =
50+
jsonToPojo(
51+
T::class.java,
3752
httpMsg.bodyString(),
3853
customAdapters,
3954
customAdaptersWithType,

0 commit comments

Comments
 (0)