acacode / swagger-typescript-api

Generate the API Client for Fetch or Axios from an OpenAPI Specification
MIT License
3.08k stars 339 forks source link

also generate mock files #499

Open RoCat opened 1 year ago

RoCat commented 1 year ago

Hello,

I use swagger-template-typescript to generate all API calls. As I also make some unit / functional tests and need to mock API calls, I sometimes had to wite things like:

fetchMock.get(
      `/api/me`,
      403
);

As you can notice neither path / query or response are typed... Is there a plan to add mock generator ?

As a "workaround" I currently use extraTemplates option to generate files I need, but I can only generate 1 file per API (no modular) ...

I'm not sure this feature is broadly needed, and my template contains some shortcuts i took for my personnal needs / api, so its not 100% generic.

Anyway here is my template, if that can help someone or be a start for a generic feature:

<%
  const { _ } = it.utils;
  let dataContracts = _.map(it.modelTypes, "name");
%>
import fetchMock from 'fetch-mock/esm/client';
<%
  let types = '';
  it.routes.combined.forEach((route) => { 
    route.routes.forEach((realRoute) => {
      types = `${types} ${realRoute.response.type}`;
      const pathParams = realRoute.request.parameters.map((p) => p.type).join(' ');
      types = `${types} ${realRoute.response.type} ${pathParams}`;
    })
  })
  dataContracts = dataContracts.filter((dc) => new RegExp(`\\b(${dc})\\b`).test(types));
%>

<% if (dataContracts.length) { %>
  import { <%~ dataContracts.join(', ') %> } from "./<%~ it.config.fileNames.dataContracts %>"
<% } %>

<% 
it.routes.combined.forEach((route) => { 
  route.routes.forEach((realRoute) => {
    const pathParams = realRoute.request.parameters.map((p) => `${p.name}${p.optional ? '?' : ''}: ${p.type}`).join(', ');
    const availableQueryFields = realRoute.request.requestParams?.properties ? Object.keys(realRoute.request.requestParams?.properties) : [];
    const responseType = `${realRoute.response.type !== 'void' ? realRoute.response.type : 'undefined'} | number`
%>
  export const <%= realRoute.routeName.usage %>Mock = (<%~ pathParams ? `${pathParams}, `: '' %>queryParams: string, response: <%~ responseType %>) => {
    const possibleParams: Array<string> = <%~ JSON.stringify(availableQueryFields) %>;
    const routeParameters = queryParams.split('&').map((s) => s.split('=')[0]);
    if(routeParameters.filter((rp) => !possibleParams.includes(rp))) {
      throw new Error('invalid query params');
    }
    return fetchMock.<%= realRoute.request.method %>(`<%= it.apiConfig.baseUrl.includes('private-api') ? '/private-api' : '/api' %><%= realRoute.request.path %>`, response || 200);
  }
<% 
  })
}) %>
mjbradvica commented 1 year ago

Another option would be to allow the path to be fully extracted so the route could be mocked in Cypress.

inomn commented 1 year ago

I'm using a combination of https://github.com/anttiviljami/mock-json-schema and https://github.com/APIDevTools/json-schema-ref-parser plus small custom script to generate mock entities for my tests.

As a result, i have mock.ts file containing all entities generated by this library file.

Scheme Example:

/** UpdateUserRequest */
export interface UpdateUserRequest {
  /** Firstname */
  firstName: string;
  /** Lastname */
  lastName: string;
  /** Timezone */
  timezone: string;
  /** An enumeration. */
  languagePreference: Language;
}

Mock example:

export const mockUpdateUserRequest: UpdateUserRequest = {"firstName":"string","lastName":"string","timezone":"string","languagePreference":Language.EN};

Where Language.EN is enum. some fields can be customized, for example for datetime i use valid iso datetime

Grawl commented 2 weeks ago

https://docs.stoplight.io/docs/prism/9528b5a8272c0-dynamic-response-generation-with-faker