openapi-library / OpenAPIValidators

Use Jest or Chai to assert that HTTP responses satisfy an OpenAPI spec
MIT License
189 stars 35 forks source link

Add possibility to work with multiple open api docs validation in 1 test #208

Closed Xotabu4 closed 3 years ago

Xotabu4 commented 3 years ago

In my current tests i need to work with multiple servers with own docs in one test:

describe('Some feature', () => {

  before(async () => {
    const axios = require('axios');
    const response = await axios.get('http://loginservice:3000/api-json');
    const openApiSpec = response.data;
    chai.use(chaiResponseValidator(openApiSpec));
  });

  it('complex flow', async () => {
    // request to service that has own doc
    const loginres = await axios.get('http://loginservice:3000/user/auth');
    expect(loginres).to.satisfyApiSpec;

    // request to another service, that also has own doc
    const res = await axios.get('http://searchservice:3000/search/', {headers: loginres.data.token});
    expect(res.status).to.equal(200);
    //
    expect(res).to.satisfyApiSpec;
  });
});

Potential solution that i see, is to create 2 chai instances:

const searchChai = require('chai')
const loginChai = require('chai')

describe('Some feature', () => {
  before(async () => {
    const axios = require('axios');
    const response = await axios.get('http://loginservice:3000/api-json');
    const openApiSpec = response.data;
    loginChai.use(chaiResponseValidator(openApiSpec));

    const axios = require('axios');
    const response = await axios.get('http://searchservice:3000/api-json');
    const openApiSpec = response.data;
    searchChai.use(chaiResponseValidator(openApiSpec));
  });

  it('complex flow', async () => {
    // request to service that has own doc
    const loginres = await axios.get('http://loginservice:3000/user/auth');
    loginChai.expect(loginres).to.satisfyApiSpec;

    // request to another service, that also has own doc
    const res = await axios.get('http://searchservice:3000/search/', {headers: loginres.data.token});
    searchChai.expect(res).to.satisfyApiSpec;
  });
});

But this looks pretty hard to support, and such approach is not possible to apply to jest version of this validatior.

Would be nice to get some api that will allow to assert against provided spec, something like:

Something like:

  it('complex flow', async () => {
    // request to service that has own doc
    const loginres = await axios.get('http://loginservice:3000/user/auth');
    expect(loginres).to.satisfyApiSpec('./loginservice.json');

    // request to another service, that also has own doc
    const res = await axios.get('http://searchservice:3000/search/', {headers: loginres.data.token});
    expect(res).to.satisfyApiSpec('./seachservice.json');
  });
rwalle61 commented 3 years ago

Thanks for this suggestion @Xotabu4. There may already be a workaround to do what you want, but let's check if it works. Even if it does, this enhancement may be nice as syntactic sugar.

I think currently expect(res).to.satisfyApiSpec validates res against the OpenAPI spec that was most recently loaded into the particular instance of chai. So although you can't currently use multiple OpenAPI specs at the same time for an instance of chai, you may be able to switch to different OpenAPI specs even in the same it block:

const axios = require('axios');

describe('Some feature', () => {
  it('complex flow', async () => {
    const { data: loginOpenApiSpec } = await axios.get('http://loginservice:3000/api-json');
    chai.use(chaiResponseValidator(loginOpenApiSpec));

    const loginres = await axios.get('http://loginservice:3000/user/auth');
    expect(loginres).to.satisfyApiSpec;

    // request to another service, that also has own doc
    const { data: searchOpenApiSpec } = await axios.get('http://searchservice:3000/api-json');
    chai.use(chaiResponseValidator(searchOpenApiSpec));

    const searchres = await axios.get('http://searchservice:3000/search/', {headers: loginres.data.token});
    expect(searchres).to.satisfyApiSpec;
  });

Does this work?

Even if it does, I agree it's a bit verbose and distracting.

If you don't need multiple OpenAPI specs in the same it block, you can separate them in different describe blocks (see how our test file uses many OpenAPI specs, each in a different describe block)

But if you do need multiple OpenAPI specs in the same it block, this enhancement may be nice as syntactic sugar

rwalle61 commented 3 years ago

Closing as there hasn't been an update for a while, but feel free to reopen or upvote this issue if anyone would like action on it 😄