Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update use of OpenApi examples to allow developers to output the examples from the endpoints #749

Open
dethell opened this issue Jan 31, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@dethell
Copy link
Collaborator

dethell commented Jan 31, 2024

Various discussion has happened around having Counterfact record/capture network sessions to capture sample JSON data responses that can be returned by default by the generated endpoints instead of .random().

After discussing it seems like a separate tool that converts a HAR file to OpenAPI is the best companion (such as https://github.com/jonluca/har-to-openapi). For the Counterfact side, presently, if an example is present, CF will pick one at random. This ticket asks for the ability to give access to the OpenApi examples so a developer can choose to use them as output or even use the examples within a context.

Example 1 (inside an endpoint TS file):

return $.response[200].examples.namedExample1

Example 2 (inside a Context):

return $.response[200].json($.context.someFunction())

and then in the context:

public function someFunction() {
   const baseData = this.spec.examples.namedExample1;
   return baseData.filter(item => <some filter logic>);
}
@dethell dethell added the enhancement New feature or request label Jan 31, 2024
@pmcelhaney
Copy link
Owner

Looks like there's another feature implied in your second example: that the context has access to the OpenAPI spec. That makes sense to me. It can be passed in the constructor of the Context class.

@pmcelhaney
Copy link
Owner

pmcelhaney commented Feb 5, 2024

Instead of

return $.response[200].examples.namedExample1

In order to keep the fluent API, we may need to do:

return $.response[200].example("namedExample1")

The reason for that is it allows continue decorating the response after selecting its content:

return $.response[200].example("namedExample1").header("some-header", "some-value")

There are two parts to implementing this feature. The runtime part can be implementing by making a copy of this random() function.

random(this: ResponseBuilder) {
if (operation.produces) {
return this.randomLegacy();
}
const response =
operation.responses[this.status ?? "default"] ??
operation.responses.default;
if (response?.content === undefined) {
return unknownStatusCodeResponse(this.status);
}
const { content } = response;
return {
...this,
content: Object.keys(content).map((type) => ({
body: convertToXmlIfNecessary(
type,
content[type]?.examples
? oneOf(
Object.values(content[type]?.examples ?? []).map(
(example) => example.value,
),
)
: JSONSchemaFaker.generate(
content[type]?.schema ?? { type: "object" },
),
content[type]?.schema,
),
type,
})),
};
},

Instead of using the oneOf() function to randomly select an example it would select the specific example passed to the function.

The other part is the ResponseBuilderFactory type:

type GenericResponseBuilder<
Response extends OpenApiResponse = OpenApiResponse,
> = [keyof Response["content"]] extends [never]
? { }
: OmitValueWhenNever<{
header: [keyof Response["headers"]] extends [never]
? never
: HeaderFunction<Response>;
html: MaybeShortcut<"text/html", Response>;
json: MaybeShortcut<"application/json", Response>;
match: [keyof Response["content"]] extends [never]
? never
: MatchFunction<Response>;
random: [keyof Response["content"]] extends [never] ? never : RandomFunction<Response>;
text: MaybeShortcut<"text/plain", Response>;
xml: MaybeShortcut<"application/xml" | "text/xml", Response>;
}>;

It will look a lot like random. The only exception is the function signature takes one argument, name: keyof Response["examples"] or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants