tjones
2023-03-07 01:40
has joined #contract-case

matt.fellows
2023-03-07 03:53
has joined #contract-case

uglyog
2023-03-07 03:53
has joined #contract-case

bethskurrie
2023-03-07 03:53
has joined #contract-case

dan.nichols52
2023-06-08 04:30
has joined #contract-case

dan.nichols52
2023-06-08 06:21
Hey all! I?m Dan, looking to take a stab at porting a Kotlin DSL for Contract Case. Sorry in advance for any spam as I ask all the silly questions

dan.nichols52
2023-06-08 06:25
First up is about defaults/required properties for configuration in the DSL?s. There is some mention of default values in the docs. I?m unsure if I should be: ? Implementing those defaults in the DSL layer ? Using the type system to help me enforce required properties, or leaving that to core validation ? Duplicating the documentation - I would like consumers (of the library) to be able to get a good understanding of required values and defaults directly from the Kdoc in their IDE

tjones
2023-06-08 06:29
? The defaults are applied by the core ? The core does validation of required properties (on the todo is to do this all in one place - it's currently a bit spread as and when the properties were queried, so I think there may be bugs. Assume the core does it, and let me know / open an issue / make a PR to case-core if it doesn't) ? Yeah, currently the documentation is duplicated in each DSL layer. I don't like this at all, so if you think of something better, I'm all ears

tjones
2023-06-08 06:30
Following the https://github.com/case-contract-testing/contract-case/blob/main/docs/maintainers/GeneralDesign.md I'd prefer a slightly annoying maintainer experience (manually updating all the docstrings) in exchange for a better user experience

tjones
2023-06-08 06:32
What I've been doing while working on the Java DSL is updating https://github.com/case-contract-testing/contract-case/blob/main/docs/maintainers/AddingDsl.md every time I find I need to make a choice or find something missing

tjones
2023-06-08 06:33
(these answers should totally go in there - if you want, you can easily put them in with github's instant PR edit button - or I can do it later)

dan.nichols52
2023-06-08 06:34
Another separate thread for this one since it?s a bit specific: ? Skipping passing nulls to the boundary layer for unset values The Java DSL https://github.com/case-contract-testing/java-dsl/blob/15d71cfbb16576aa1d113220738a1416e518dd97/src/main/java/io/contract_testing/contractcase/BoundaryConfigMapper.java#L60 conditionally maps values to the boundary if they are not null. ``` if (config.brokerBaseUrl != null) { builder.brokerBaseUrl(config.brokerBaseUrl); }``` Is there a reason we don?t map everything anyway, even if the property is null? Looking at the Jsii types it seems like these should be nullable for the most part

tjones
2023-06-08 06:34
It would be AWESOME if all the javadoc / docstrings / tsdoc etc was kept up to date automatically, but I don't know how to solve that - even if we had a way to instantly update everything from a master source, you don't actually want exactly the same text in each language

dan.nichols52
2023-06-08 06:36
Yeah there are some minor variations depending on the ergonomics of each DSL, so a shared javadoc generation thing would probably have its own headaches

tjones
2023-06-08 06:36
That's just personal preference. I wanted it to be consistent, so I did each one explicitly. That particular one does no mapping, but it's implicitly: ``` if (config.brokerBaseUrl != null) { builder.brokerBaseUrl(BrokerBaseUrlMapper.map(config.brokerBaseUrl)); }``` I wanted the mappers not to have to know whether or not they have the thing

tjones
2023-06-08 06:37
Also I don't really know how to Java any more?

tjones
2023-06-08 06:37
You don't have to do it the same way, as long as the exposed interface is the same

tjones
2023-06-08 06:37
(to both the user and `case-boundary`)

tjones
2023-06-08 06:38
With that explicit check you don't have to start each mapper with `if(thing == null) return null`

tjones
2023-06-08 06:38
Probably there's a MUCH nicer way to do it in kotlin :raised_hands:

dan.nichols52
2023-06-08 06:38
> The core does validation of required properties The main reason I ask about this one specifically, is that we can get help from the type system in the kotlin DSL, so users get faster feedback on mis-use

dan.nichols52
2023-06-08 06:41
Yeah in kotlin I?m doing something like: ```build(ContractCaseBoundaryConfig::builder) { testRunId(testRunId) providerName(providerName) consumerName(consumerName) // ... }``` So just wanna save a bunch of ```if (brokerBaseUrl != null) brokerBaseUrl(brokerBaseUrl)```

tjones
2023-06-08 06:41
Right yep

tjones
2023-06-08 06:41
I like it

tjones
2023-06-08 06:41
I think in Java I'd have to do that check anyway, maybe not for primitives

tjones
2023-06-08 06:42
Yeah....

tjones
2023-06-08 06:43
So, what I did there is - the boundary is very permissive. Like, it lets you pass ANYTHING as the mock example description

tjones
2023-06-08 06:43
which is wrong. You can't actually pass anything.

tjones
2023-06-08 06:43
My thinking is that the DSL would be more restrictive

tjones
2023-06-08 06:43
there's a type for `AnyMockDescription`

tjones
2023-06-08 06:43
and there's an `AnyMatcher`, but currently that's not used

tjones
2023-06-08 06:44
So, I think that it's ok to make the type system helpful where possible

tjones
2023-06-08 06:44
see the enums in Java, whereas TS has strings

tjones
2023-06-08 06:45
There's one place where you have to do validation, which is the combinations of testResponse and trigger functions

tjones
2023-06-08 06:46
since these must be combined before being passed to the boundary (as the boundary can't take the native object returned by `trigger` and pass it to `testResponse`), the only place we can validate them is in the DSL

dan.nichols52
2023-06-08 06:50
hmm ok I?ll keep an eye out for that exception

dan.nichols52
2023-06-08 06:51
Will favour language idioms over strictly not validating anything - might bite me later but we?ll see

dan.nichols52
2023-06-08 06:54
Ok and for the collection types like the map of state handlers, do we prefer a null, or an empty map?

tjones
2023-06-08 06:57
Either should work. (Implementation details: The definition at the boundary is expecting a null, but it becomes an empty map when it goes into the core anyway)

dan.nichols52
2023-06-08 06:58
Yeah I figured as much, cheers

tjones
2023-06-08 06:58
The value here is in not needing to update several places when the acceptable values change

tjones
2023-06-08 06:58
But it's more valuable to be helpful to the user

dan.nichols52
2023-06-08 06:59
Yeah totally understand wanting to keep as much as possible in core

tjones
2023-06-08 06:59
I didn't do it in the type system, because the autotranslation only accepts a subset of Typescript.

tjones
2023-06-08 06:59
(eg, it doesn't let you do unions, which is what you would do idiomatically in TS)

dan.nichols52
2023-06-08 06:59
The ts-dsl would allow for this though right

tjones
2023-06-08 06:59
Also: A validation error at runtime is more helpful.

tjones
2023-06-08 07:00
It does.

tjones
2023-06-08 07:01
Runtime validation means we can give arbitrary error messages. Whereas trying to do it in the typesystem just leaves users being like "why isn't there a constructor with this invalid option combination" or something

tjones
2023-06-08 07:16
For preferences - I prefer nothing is null, ever. But I didn't want to do a lot of `Optional<>` in Java

tjones
2023-06-08 07:17
but that's just preference. I won't make you do it if you prefer something else.

tjones
2023-06-08 07:17
The TS dsl won't let you do: ```someProp: undefined``` but it will let you omit `someProp`

dan.nichols52
2023-06-08 07:17
Yeah agree

tjones
2023-06-08 07:18
I thought you might :joy:

abubics
2023-06-08 07:18
has joined #contract-case

dan.nichols52
2023-06-08 07:18
Kinda why I want defaults in the DSL layer

tjones
2023-06-08 07:19
Also, @dan.nichols52 - I mentioned this elsewhere, but it should go here too - frustratingly the JSii boundary won't work at all until https://github.com/aws/jsii/issues/4133. And I think we (I?) are going to have to fix it: https://github.com/aws/jsii/issues/4133

dan.nichols52
2023-06-08 07:19
How hard is it to expose constants from Jsii. Could rely on boundary instead of hardcoding in dsl

tjones
2023-06-08 07:20
However, worst case, if you build something to the `case-boundary` API, then it's replaceable - since all that layer does is contact the core.

dan.nichols52
2023-06-08 07:21
Depending on how that issue goes I might look into a JavaScript jsii binding instead of JVM, since I was going to have to do that to support kotlin multiplatform anyway

tjones
2023-06-08 07:22
Yep. I can expose defaults

tjones
2023-06-08 07:22
That's a really good idea

tjones
2023-06-08 07:22
There already are exposed constants for acceptable values for `logLevel`, `publish`, etc

dan.nichols52
2023-06-08 07:23
I think those are already in use to build enums in java DSL yeah?

tjones
2023-06-08 07:23
Javascript JSii is just the JS lib anyway

tjones
2023-06-08 07:23
(with no translation)

dan.nichols52
2023-06-08 07:23
Ahh right ok

tjones
2023-06-08 07:24
the TS DSL is in the main repo, under packages/contractcase-jest-dsl (I think)

dan.nichols52
2023-06-08 07:25
Hmm actually I think I need a Jsii target for every kotlin target I want to support. So in the end need JavaScript, and jvm

tjones
2023-06-08 07:25
yeppers

dan.nichols52
2023-06-09 06:14
Can I confirm something from the docs? https://case.contract-testing.io/docs/reference/triggers#providing-triggers-during-contract-definition. Gonna paraphrase the docs to see if my understanding is correct. The 3 ways to define a trigger are: 1. In the `runExample` arguments (for a successful response) 2. In the `runRejectingExample` arguments (for an unsuccessful response) 3. A group of named triggers in the ContractCaseConfig object (for contract verification) The docs has the usage of (1) as: ```await contract.runExample({ states: [...], // These `...` are not spreads, just for brevity definition: willSendHttpRequest(...), }, { // Presumably the ContractCaseConfig object as an override for the parent config trigger: (config: HttpRequestConfig) => {}, testResponse: (user) => {} })``` But looking in https://github.com/case-contract-testing/contract-case/blob/1eeef00cf6eef5ac942003544d0496fd466effa2/packages/case-core/src/index.http.client.define.spec.ts#L144, the triggers are defined as: ```contract.runRejectingExample({ states: [...], definition: willSendHttpRequest(...), trigger: (config: HttpRequestConfig) => { ... }, testResponse: (user) => { ... }, });``` Are both of these patterns going to be supported? Can I converge on just one of these in the DSL? Looks like the former example is more aligned to the boundary schema, but the latter feels more natural. From https://github.com/case-contract-testing/contract-case/blob/main/docs/maintainers/AddingDsl.md#implementing-the-contractdefiner-class there is a TODO. Is this just going to say that a trigger needs to be paired with a response (whether success or rejecting), and you can?t have one without the other? > TODO: Describe how to map trigger / testResponse - this is the only place where you may throw a `CaseConfigurationError`

tjones
2023-06-09 06:23
> Are both of these patterns going to be supported? Can I converge on just one of these in the DSL? No, just the `{states, defintion}, {...config}` one. The reason for this is because the first argument (states/definition) is just data, the second (config) is test setup. Triggers and test response functions are just > But looking in some examples in the codebase, (....) That's an internal test, not a test written using the DSL. The API is different (I would like to update it to match the boundary API though - there's no technical / conceptual reason for it to be different). > A group of named triggers in the ContractCaseConfig object (for contract verification) One clarification - the main usecase for this is verification, but it's also valid for definition. Eg, you could define all the triggers at the top so you don't have to repeat them if you've got a lot of different states for the same endpoint.

dan.nichols52
2023-06-09 06:24
Thanks for the response

tjones
2023-06-09 06:24
> From the DSL ContractDefiner setup instructions there is a TODO. Is this just going to say that a trigger needs to be paired with a response (whether success or rejecting), and you can?t have one without the other? Yes, that's right. It has to be done in the host code (Kotlin) because JSii can't handle arbitrary host objects - so the core can't take the `trigger`'s return value and pass it to the `testResponse` function

tjones
2023-06-09 06:24
Ultimately, `trigger` and `testResponse` will be removed from the core

tjones
2023-06-09 06:24
This substantially simplifies it

dan.nichols52
2023-06-09 06:24
That?s why we are allowed to throw ContractCaseConfigurationError there


tjones
2023-06-09 06:25
> No, just the {states, defintion}, {...config} one. The reason for this is because the first argument (states/definition) is just data, the second (config) is test setup. Triggers and test response functions are just If you think this doesn't make sense, I'm open to an alternative DSL

dan.nichols52
2023-06-09 06:26
It?s a bit confusing to me, just need to figure out how to say why

tjones
2023-06-09 06:26
er, that should say: > Triggers and test response functions are just test configuration

tjones
2023-06-09 06:26
The point is the first argument is what's actually going in the contract

tjones
2023-06-09 06:26
everything else doesn't.

dan.nichols52
2023-06-09 06:27
I think the confusing thing is that in a global context, the group of triggers makes sense - they?re all named, and they can have success or error functions, or both

dan.nichols52
2023-06-09 06:27
But in the runExample context, you?re allowed to have a single trigger (and paired response function) in the top level config object

dan.nichols52
2023-06-09 06:28
So are the triggers on the individual versions named/keyed? Do they need to be?

tjones
2023-06-09 06:28
> But in the runExample context, you?re allowed to have a single trigger (and paired response function) in the top level config object Yep! That's unlikely to be common. But you can. You should be able to say: ```defineContract(triggers) <-- where triggers doesn't have testResponse functions``` then: ```runExample(whatever, { testResponse: someFunc} )``` But at the moment, you can't.

tjones
2023-06-09 06:28
> So are the triggers on the individual versions named/keyed? Do they need to be? Yes

tjones
2023-06-09 06:29
Otherwise the core doesn't know which ones to use

tjones
2023-06-09 06:29
Oh right! Let me get you a link that tells you how to do that


tjones
2023-06-09 06:31
````${requestName}::${responseName}````

tjones
2023-06-09 06:31
So, triggerKey, testResponseKey, joined with `"::"`

dan.nichols52
2023-06-09 06:31
Right so they?re implicitly keyed from the ITriggerFunction

tjones
2023-06-09 06:32
Explicitly?

tjones
2023-06-09 06:32
Not implicit

dan.nichols52
2023-06-09 06:32
^ that code is in the boundary

tjones
2023-06-09 06:32
Ah, no, not from `ITriggerFunction`

dan.nichols52
2023-06-09 06:32
The keying is implicit to the end user right

dan.nichols52
2023-06-09 06:33
> Sets the value of getTriggerAndTest > Params: > triggerAndTest ? Call the native trigger and test function (if any) for this interaction pair. Keyed by ${requestName}::${responseName} > Returns: > this This is the boundary config option I?m looking at

tjones
2023-06-09 06:33
> ^ that code is in the boundary No it isn't. It's in the jest package

tjones
2023-06-09 06:34
> Keyed by ${requestName}::${responseName} oops.


tjones
2023-06-09 06:34
This line should be deleted

dan.nichols52
2023-06-09 06:34
I still don?t get how the `triggerAndTest` config can be keyed by only passing in an ITriggerFunction

tjones
2023-06-09 06:34
there's no key for `triggerAndTest`. It doesn't need to be keyed

tjones
2023-06-09 06:34
Sorry about that, documentation is wrong

dan.nichols52
2023-06-09 06:35
So keying happens in `triggerAndTests` (I have that in my dsl), but not in `triggerAndTest`

dan.nichols52
2023-06-09 06:36
Ok so no keying for `triggerAndTest` does make sense, but that means it should only ever be usable from `runExample` and `runRejectingExample` right?

dan.nichols52
2023-06-09 06:36
And not on the global config object?


tjones
2023-06-09 06:36
Fixed the doc

tjones
2023-06-09 06:36
> So keying happens in triggerAndTests (I have that in my dsl), but not in triggerAndTest Correct

tjones
2023-06-09 06:37
> Ok so no keying for triggerAndTest does make sense, but that means it should only ever be usable from runExample and runRejectingExample right? Well. Yes ish. You could define it at the top level. It would work.

tjones
2023-06-09 06:37
You might use that if you only have one endpoint but like 5 tests

tjones
2023-06-09 06:37
you'd put `trigger` at the top, and then `testResponse` in each test

dan.nichols52
2023-06-09 06:38
So you have the same trigger pair for every test

dan.nichols52
2023-06-09 06:38
oh


dan.nichols52
2023-06-09 06:38
Same setup

dan.nichols52
2023-06-09 06:38
Different assertions

tjones
2023-06-09 06:38
So um, confession time: The undocumented bits might be the trickiest

tjones
2023-06-09 06:39
You have to remember the main config object and check it for the trigger / testResponse / testErrorResponse when you're looking to see if you have them

tjones
2023-06-09 06:39
I might not have implemented that in the Java one :confused:

dan.nichols52
2023-06-09 06:39
Yeah I?m following the java dsl for the most part :sweat_smile:

dan.nichols52
2023-06-09 06:39
Ok so that validation needs to happen on the merged config

dan.nichols52
2023-06-09 06:40
I guess the BoundaryContractDefiner doesn?t do that internally?

tjones
2023-06-09 06:40
> Yeah I?m following the java dsl for the most part It's not fully complete, because at the moment I can't test it

tjones
2023-06-09 06:41
It can't. Because they're joined at that point.

dan.nichols52
2023-06-09 06:41
Yeah I notice I need to map the matchers which aren?t in the java version yet

tjones
2023-06-09 06:41
I just looked at the TS DSL


tjones
2023-06-09 06:41
They are

tjones
2023-06-09 06:41
You can just use the JSii package

dan.nichols52
2023-06-09 06:41
Yeah you pass additional config to definer.runExample right

tjones
2023-06-09 06:41
The TS DSL needs to be updated to use the JSii package

tjones
2023-06-09 06:42
instead of the other way around

tjones
2023-06-09 06:42
You could build builders for them

tjones
2023-06-09 06:42
but it will be a lot of work

dan.nichols52
2023-06-09 06:42
~So my plan~ scratch that I have no plan

tjones
2023-06-09 06:43
in Kotlin, you'd be better off just using the constructor, I think ```ArrayEachEntryMatches(AnyString("foo"))``` etc

tjones
2023-06-09 06:43
So the matchers do nothing. They are only data.

tjones
2023-06-09 06:44
There's no behaviour. They produce objects that can be serialised to JSON. Unfortunately, because the properties are not valid names in most languages, they don't get builders built for free by JSii

dan.nichols52
2023-06-09 06:44
Ok, will see about the matchers when I get there

tjones
2023-06-09 06:45
The Java test that I have there is the best example of how to use them

tjones
2023-06-09 06:45
....it's possible I didn't commit that

tjones
2023-06-09 06:45
because it doesn't work

tjones
2023-06-09 06:45
I will check after work

dan.nichols52
2023-06-09 06:45
Yeah fair

dan.nichols52
2023-06-09 06:45
No stress

tjones
2023-06-09 06:45
Worst case I'll put it on a branch for you

dan.nichols52
2023-06-09 06:46
The triggers are still confusing me

dan.nichols52
2023-06-09 06:47
In java dsl world, `IndividualSuccessTestConfig` ~must~ may define a `trigger` and a `testResponse` pair, but that?s not technically right, because you may have defined a top level `trigger` on the top level config?


tjones
2023-06-09 06:48
I messed that up

tjones
2023-06-09 06:48
I remember fixing it though. I wonder if it's fixed on the non-pushed code

dan.nichols52
2023-06-09 06:48
Ok so a lone `trigger` is valid on `ContractCaseConfig`

tjones
2023-06-09 06:48
Yes, in isolation

tjones
2023-06-09 06:48
no, in aggregate

tjones
2023-06-09 06:49
if that makes sense?

dan.nichols52
2023-06-09 06:49
Yeah but (at least in java), the contract definer doesn?t do any aggregation of config

tjones
2023-06-09 06:50
Yep. The only reason you would need to do that is for triggers.

tjones
2023-06-09 06:50
I don't think the TS DSL does either.

dan.nichols52
2023-06-09 06:50
So should the mapSuccessExample validation be removed from the dsl?

tjones
2023-06-09 06:50
But they both should.

dan.nichols52
2023-06-09 06:50
Oh so the DSL?s _should_ be doing config aggregation

tjones
2023-06-09 06:50
Yes, only for that field

tjones
2023-06-09 06:50
it's the only one it needs to know about

tjones
2023-06-09 06:51
it's a really annoying leaky concern.

tjones
2023-06-09 06:51
There's no nice way to do it.

dan.nichols52
2023-06-09 06:51
Ok so do that validation in `runExample` and `runThrowingExample` (somewhere down the mapping chain)

tjones
2023-06-09 06:51
(as far as I can see)


dan.nichols52
2023-06-09 06:51
Ok cool

tjones
2023-06-09 06:52
Oh hey, I want to make tests for these

tjones
2023-06-09 06:52
but I can't think of how to do it

tjones
2023-06-09 06:52
I was thinking, a list of tests in one existing DSL

tjones
2023-06-09 06:52
with "please port this to your DSL and make sure they all pass"

tjones
2023-06-09 06:52
What do you think?

dan.nichols52
2023-06-09 06:53
I have been thinking about making a `sample` or `example` module inside the dsl codebase that has a simple ktor server and client

tjones
2023-06-09 06:53
Yeah, you'll need that for when you want to do tests

tjones
2023-06-09 06:53
See the DSL test in Typescript

tjones
2023-06-09 06:53
My plan was to make all of those consistent

tjones
2023-06-09 06:53
so they have the same tests in all the languages

dan.nichols52
2023-06-09 06:53
Can you just import a contract(s) from a different dsl and run the verification

tjones
2023-06-09 06:53
You need two types of tests though

tjones
2023-06-09 06:53
one for examples

tjones
2023-06-09 06:53
(yes, for verification)

dan.nichols52
2023-06-09 06:54
Not for definition right

tjones
2023-06-09 06:54
one for examples, and one for all the different ways of executing tests.

tjones
2023-06-09 06:54
> Not for definition right Yes, that's right

tjones
2023-06-09 06:54
Because there are a lot of different ways to specify tests

dan.nichols52
2023-06-09 06:55
Yeah saying, ?port all of these tests? is good, but you?ll get missed tests

tjones
2023-06-09 06:55
eg, the core tests include: ```httpResponse({ status: 200 })``` and ```httpResponse({ status: "200" })``` and ```httpResponse({ status: httpStatus(200) })``` and ```httpResponse({ status: httpStatus("2XX") })```

tjones
2023-06-09 06:56
> Yeah saying, ?port all of these tests? is good, but you?ll get missed tests My thinking was each test would get an ID. Then later I could parse the test output and produce a report of which IDs are missing for each language.

tjones
2023-06-09 06:56
But again, I haven't really thought it through.

dan.nichols52
2023-06-09 06:56
Yeah that can work

dan.nichols52
2023-06-09 06:56
You?d just need review of each

tjones
2023-06-09 06:56
Another thing I was thinking is to add some special matchers that exist only for testing

dan.nichols52
2023-06-09 06:57
I would love to have example code used both in tests, and documentation

tjones
2023-06-09 06:57
like ```runExample( CoreWillThrowConfigurationError, {config} )```

tjones
2023-06-09 06:57
> I would love to have example code used both in tests, and documentation Yes, but the problem here is that you still need separate examples, as I mentioned above

dan.nichols52
2023-06-09 06:58
hmm

tjones
2023-06-09 06:58
Otherwise your "have a look at this file to see how to use it" is too confusing

tjones
2023-06-09 06:59
because you could only read those if you already know how to use it, because there would be repeat specifications. Like: ```defineContract({triggers}) runExample(definition)``` and ```defineContract() runExample(definition, {triggers})```

dan.nichols52
2023-06-09 06:59
I don?t know if there are tools for this, but something like the gradle docs would be good for this: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_scripts_are_code Since there are multiple languages to do the same thing

tjones
2023-06-09 06:59
What do you mean?

dan.nichols52
2023-06-09 07:00
I?m conflating too many things, dw about me haahhaaha

tjones
2023-06-09 07:00
If you're talking about the main docs, I was thinking that the docs would have tabs for each code example

dan.nichols52
2023-06-09 07:00
I want code samples in documentation to be backed by concrete tests

tjones
2023-06-09 07:00
Oh yes. That's definitely possible

tjones
2023-06-09 07:00
That's a further down the line thing

dan.nichols52
2023-06-09 07:00
Yeah totally

tjones
2023-06-09 07:00
(I think)

tjones
2023-06-09 07:01
I think we'll need some kind of parser so you can pull out bits for the docs. But I'm sure something like that exists already.

tjones
2023-06-09 07:02
to avoid having the whole `import blah / define contract` in each `runExample` example

tjones
2023-06-09 07:02
Ok so

tjones
2023-06-09 07:02
fun aside

tjones
2023-06-09 07:02
The `definition` part is just data, right?

tjones
2023-06-09 07:03
Soooo when we implement `callFunction` mock types (which is like how Pact does message pacts), we could test the DSL with ContractCase

tjones
2023-06-09 07:03
:exploding_head:

dan.nichols52
2023-06-09 07:05
yes?

dan.nichols52
2023-06-09 07:05
I don?t know hahah

tjones
2023-06-09 07:13
Ok, so the Java DSL didn?t have the crash handler in it

tjones
2023-06-09 07:13
it does now

tjones
2023-06-09 07:15
I?ll paste an example of the Java DSL

dan.nichols52
2023-06-09 07:16
Ahh ok nice cheers

tjones
2023-06-09 07:16
it ?works? in that configuration errors are handled

dan.nichols52
2023-06-09 07:17
Ok that?s good

tjones
2023-06-09 07:24
@dan.nichols52 here?s an example use of the Java DSL: Some points: ? This is a modification of https://github.com/pactflow/example-consumer-java-junit ? The Java ContractCase DSL is SUPER wordy and unpleasant in places. Once I?ve fixed the JSii issue, I plan to do a parse to make it nicer to use / less wordy Define contract: ``` contract = new ContractDefiner( ContractCaseConfig.ContractCaseConfigBuilder.aContractCaseConfig() .providerName("Java Example HTTP Server") .consumerName("Java Example HTTP Client") .publish(PublishType.NEVER) .build());``` Run example: ``` @Test public void getProduct() { contract.runExample( new ExampleDefinition<WillSendHttpRequest>(new ArrayList<>(), new WillSendHttpRequest( HttpExample.builder() .request( new HttpRequest( HttpRequestExample.builder() .path("/product/10") .method("GET") .build() ) ).response( new HttpResponse( HttpResponseExample .builder() .status(200) .body( Map.of("name", new AnyString("product name"), "type", new AnyString("product series"), "id", new AnyString("5cc989d0-d800-434c-b4bb-b1268499e850") ) ).build() ) ).build())), IndividualSuccessTestConfig.IndividualSuccessTestConfigBuilder.<Product>builder() .withProviderName("Java Example HTTP Server") .withConsumerName("Java Example HTTP Client") .withLogLevel(LogLevel.DEEP_MAINTAINER_DEBUG) .withTrigger( config -> { try { return new ProductClient().setUrl( config.get("baseUrl").toString().replace("localhost", "127.0.0.1")) .getProduct("10"); } catch (IOException e) { throw new RuntimeException(e); } }) .withTestResponse( product -> { assertThat(product.getId(), is("5cc989d0-d800-434c-b4bb-b1268499e850")); }).build() );```

tjones
2023-06-09 07:27
If you get as far as running it, this example above should produce the following log:

tjones
2023-06-09 07:27
Oh yeah, also, there is currently no logging from `case-boundary`. I?m planning to put some in, at the `deepMaintainerDebug` level

dan.nichols52
2023-06-09 07:28
Ok, I?ll post a similar example of the kotlin DSL when I get a chance, but am about to run off

tjones
2023-06-09 07:29
Samesies

tjones
2023-06-09 07:29
I?m gonna work on that bug on Monday

tjones
2023-06-09 07:29
I think it will only require changes in every JSii package

tjones
2023-06-09 07:30
(not actually, but?. maybe)

dan.nichols52
2023-06-09 07:31
Seems like a pretty big overhaul change for jsii

tjones
2023-06-09 07:31
?..yeah

tjones
2023-06-09 07:32
I might be able to get away with just making one side non-blocking

tjones
2023-06-09 07:33
Or we could just do an alternate approach and build a case-boundary that communicates with the core some other way

tjones
2023-06-09 07:33
It?s possible that THAT could be done with JSii.

tjones
2023-06-09 08:45
Published some new versions that fix JSii load errors: ```def caseCoreVersion = "0.13.0" dependencies { api "io.contract-testing.contractcase:case_example_mock_types:${caseCoreVersion}" api "io.contract-testing.contractcase:test-equivalence-matchers:${caseCoreVersion}" implementation 'io.contract-testing.contractcase:case_boundary:0.6.3'```

tjones
2023-06-09 08:46
Breaking changes: ```import io.contract_testing.contractcase.case_example_mock_types.AnyMockDescriptor;``` becomes: ```import io.contract_testing.contractcase.case_example_mock_types.base.AnyMockDescriptor;```

dan.nichols52
2023-06-09 11:47
There's some kotlin-js magic libraries I had a quick squiz at today but the solution is not guaranteed, and pretty sure non trivial, and would only work for kotlin (although for every platform)

dan.nichols52
2023-06-10 23:36
Ok I?m getting the same logs now

dan.nichols52
2023-06-10 23:37
Getting an error I?d expect in that the server is not ever called, but that?s because my trigger is empty

dan.nichols52
2023-06-11 01:23
Is this the error I would expect from this Jsii issue?

dan.nichols52
2023-06-11 01:23
My contract

dan.nichols52
2023-06-11 01:26
Have got the test code on this branch if you want to check it out: https://github.com/dan-nichols/contract-case-kotlin/tree/test/add-client-contract

tjones
2023-06-11 01:29
Potentially. The jsii error is that the mock server can?t respond

tjones
2023-06-11 01:29
So the framework will continue if your trigger throws or returns

tjones
2023-06-11 01:29
But not if it just waits

dan.nichols52
2023-06-11 01:30
Hmm yeah the test might be waiting on a response

dan.nichols52
2023-06-11 01:30
The error is a socket timeout so would make sense


tjones
2023-06-11 01:31
Looks like you?ve done a nice job on the printing!

tjones
2023-06-11 01:31
I indented some of it in the other implementations

tjones
2023-06-11 01:31
But it?s hard to tell that without examples

dan.nichols52
2023-06-11 01:32
I did a naive port of the java implementation

dan.nichols52
2023-06-11 01:33
I want to use a different library that?s pure kotlin though, as the only jvm dependency (aside from Jsii boundary) is that ansii helper

tjones
2023-06-11 01:33
Hmm. The Java impl should have the indenting but maybe I did it wrong

tjones
2023-06-11 01:33
That style would actually look nice in Kotlin, though!

dan.nichols52
2023-06-11 01:34
I do have indenting in the logger/printer but haven?t tested any of it so chances are it?s just broken

tjones
2023-06-11 01:36
Well, it might be broken in the Java since I haven?t tested it either

tjones
2023-06-11 01:37
I?m gonna work on the jsii bug tomorrow

tjones
2023-06-11 10:50
@dan.nichols52 What do you need to get Kotlin Native working? C?

tjones
2023-06-11 10:50
(or is it not Kotlin Native that you?re using?)

tjones
2023-06-11 10:50
That DSL is really nice for Kotlin :raised_hands:

dan.nichols52
2023-06-11 10:50
I think it?s C for kotlin Native

dan.nichols52
2023-06-11 10:51
If using JSii, which I don?t think is actually supported

tjones
2023-06-11 10:53
I can probably make another solution for C. Do you need it though?

tjones
2023-06-11 10:53
Or are you using some other thing?

tjones
2023-06-11 10:53
Also: Should the boundary expose the ANSI codes?

dan.nichols52
2023-06-11 10:53
Eventually I think I?ll lean on cashapp?s Zipline for the kotlin DSL, which will let me run javascript from kotlin native code

tjones
2023-06-11 10:54
I didn?t originally colour the strings, because I thought the host languages might not support the colours


dan.nichols52
2023-06-11 10:55
In that case I?d actually stop using Jsii entirely tbh

tjones
2023-06-11 10:55
You might be able to just modify the jest-dsl

dan.nichols52
2023-06-11 10:55
just. use it for all kotlin targets

tjones
2023-06-11 10:55
since it?s already a client of the case-boundary

tjones
2023-06-11 10:56
and in JS

dan.nichols52
2023-06-11 10:56
I?d hope to consume case-boundary from npm yeah>?

tjones
2023-06-11 10:56
yes, but if you need to write JS for kotlin/js (I don?t know how it works), there?s already a fully written consumer of case-boundary

dan.nichols52
2023-06-11 10:57
I need to do kotlin ?bindings? for javascript objects in kotlin-js, so I don?t think I get anything for free from jest dsl

tjones
2023-06-11 10:58
Right, makes sense

tjones
2023-06-11 10:58
?.would that approach also work for consuming it from Java?

dan.nichols52
2023-06-11 10:58
:shrug: I almost didn?t bother tbh. How important is it for the logs to be colourful

tjones
2023-06-11 10:59
Since nice to use is the top value, I?d say fairly

dan.nichols52
2023-06-11 10:59
Yeah I?d be consuming the kotlin-js from kotlin-jvm

tjones
2023-06-11 10:59
but it?s not more important than it ?. actually working

tjones
2023-06-11 10:59
and having features

dan.nichols52
2023-06-11 10:59
and the kotlin-js would be mapping/packaging javascript

dan.nichols52
2023-06-11 10:59
All of this is not proven and would be very experimental

tjones
2023-06-11 10:59
One of the next tasks is to automate the generation of the matcher documentation

dan.nichols52
2023-06-11 11:00
The use-case for Zipline is to distribute kotlin code to mobile apps over the network

tjones
2023-06-11 11:00
it?s pretty easy, it just needs to be done. The matchers are already in modules, so the approach would be to use `jsii-docgen` with the json output, parse that and either generate Markdown, or make a react component that can read the json.

dan.nichols52
2023-06-11 11:00
So I?d essentially be using it without network

tjones
2023-06-11 11:01
This sounds?. slightly more risky than my jsii plan, which ended up not quite working

tjones
2023-06-11 11:01
but hey

tjones
2023-06-11 11:02
It also sounds like the best approach, at least that I?m aware of

dan.nichols52
2023-06-11 11:03
Yeah it?s risky but am planning to use it as an alternate to Jsii

dan.nichols52
2023-06-11 11:03
If it works, I get all kotlin platforms supported

joshua.ellis
2023-09-20 06:40
has joined #contract-case