Follow this guide when you want to add a new configuration option to configure the core behaviour of ContractCase.
ContractCase can take configuration options that change the core behaviour of the matching engine, test runner, contract writing, and broker configuration (etc).
The configuration itself isn't passed around, instead it becomes properties on the context object (RunContext) that tells ContractCase how it is running.
This flattening into one object allows ContractCase to be agnostic to how it was configured, and consistent about precedence of configuration methods.
Note that configuration should be in the _case:currentRun:context: namespace and not the _case:context: namespace. This is because _case:context: properties are able to be overwritten by matchers - which generally isn't desirable for configuration.
Ideally, it's best if ContractCase can check one value in the configuration to determine how one setting should behave, instead of needing to check multiple different values.
This means that you may want to add a composite property to the context instead of a property that's the same as the configuration setting.
Don't spread defaults throughout the code.
If you're wanting to configure a particular interaction type, then instead refer to the interaction plugin definitions (eg MockConfig).
The core needs to know your configuration property
- Add your property to the core's
CaseConfig(usuallyBaseCaseConfig). If your property is required for ContractCase to operate, then make it required here (even if users aren't expected to specify it) - Add the option to the
RunContexttype. This is made of a few different sub-contexts, for use by parts of the ecosystem that don't have access to the full config object. It may be appropriate to add it to one of the sub-contexts instead of directly. Note that you might want to add a composite property here instead. - Ensure the value is mapped between
CaseConfigandRunContextappropriately. For most configuration properties, the methodconfigToRunContextis sufficient and doesn't need to be modified. - If your config has default values, add them to DEFAULT_CONFIG / dependencies.ts as appropriate
- Add it to
ContractCaseBoundaryConfig. This should only contain primitive types, so that different connector implementations are possible. Keep this defined in the same order as the CaseConfig object. This object should be documented, and should specify what the default is. - Add it to the
convertConfigfunction. This function should validate the values can be assigned to the typescript CaseConfig, but do no other validation. It may also normalise if the result is unambiguous (eg, you can interpretsomePropertyasSOME_PROPERTY). You can assume that the type passed in to this function is correct- if it's astringin the boundary config, then it's safe to use as astringin theCaseConfig. - Add it to the
.protoversion of the config object incase-connector-proto, then runnpm run build:protoandnpm run lint:fix:protoin that package (this tool fails on the first run to indicate that it changed something. Run it again to confirm it is now fixed). Note also that the proto expects snake_case variable names. - Add it to
ContractCaseConnectorConfig, using the same rules as the boundary config. TODO: Replace the boundary config with the connector config so that we only have to do one mapping here. - Add it to
mapAllConfigFieldsin the grpc connector
- For JS, this is
ContractCaseConfigand the associated mapper toContractCaseBoundaryConfig - For Java, this is
ContractCaseConfig,IndividualFailedTestConfig,IndividualSuccessTestConfig,ContractCaseConnectorConfig, and their associated builders. You will also need to add mappers inConnectorConfigMapperandConnectorOutgoingMapper.
Add it to the configuration page in the reference section in /packages/documentation and and other pages.