chris6owens
chris6owens

Reputation: 1

Is there a convenient way to update stubbed API calls when the app is updated to expect a new JSON format?

Our app is under heavy development, and our API JSON formats are constantly changing. Here's a simplified example:

{
    "succeeded": true,
    "message": null,
    "data": {
        "purchaseOrderId": "1f7968e2-f18e-417b-9e7b-1c35e5bdd465",
        "vendor": {
            "vendorId": "7a76533d-9c8b-4ac0-85c0-df89eaa3cb0e",
            "name": "Owens Brothers",
            "number": "VND-8888"
        },
        "purchaseOrderNumber": 101
    },
    "errors": null
};

But then we learn we need to include additional info:

{
    "succeeded": true,
    "message": null,
    "data": {
        "purchaseOrderId": "1f7968e2-f18e-417b-9e7b-1c35e5bdd465",
        "vendor": {
            "vendorId": "7a76533d-9c8b-4ac0-85c0-df89eaa3cb0e",
            "name": "Owens Brothers",
            "number": "VND-8888"
        },
        "buyer": {
            "buyerId": "629f21c0-c27b-42d7-9a3e-bb5f9d7a268a",
            "fullName": "Allen Armstrong"
        },
        "purchaseOrderNumber": 101
    },
    "errors": null
};

Obviously this "breaks" the test. The frontend expects the new format, but gets the old format from my stubbed API call.

When this happens, I usually go to the live app, put it into a state that correctly populates the stuff I want to test, and use the Chrome inspect tool to get the contents of the response.

Then I sometimes edit it to make it exactly what I want and paste it into my cypress stub function.

Is there a better workflow for this kind of thing?

Upvotes: 0

Views: 142

Answers (1)

user16695029
user16695029

Reputation: 4511

If you wish to update the fixture with the buyer branch whilst retaining values already mocked (for example purchaseOrderId value), you can use lodash merge().

it('updates a fixture with new structure', () => {

  const currentFixture = {
    data: {
      purchaseOrderId: 'mock-this-value',    // mock is providing this value
      vendor: {
        vendorId: '7a76533d-9c8b-4ac0-85c0-df89eaa3cb0e',
      },
      purchaseOrderNumber: 101,
    },
  }

  const newStructure = {
    data: {
      purchaseOrderId: '1f7968e2-f18e-417b-9e7b-1c35e5bdd465',
      vendor: {
        vendorId: '7a76533d-9c8b-4ac0-85c0-df89eaa3cb0e',
      },
      buyer: {                             
        buyerId: '629f21c0-c27b-42d7-9a3e-bb5f9d7a268a',
      },
      purchaseOrderNumber: 101,
    },
  }

  const revisedFixture = Cypress._.merge(newStructure, currentFixture)

  // Does revised fixture have the new struture?
  expect(revisedFixture.data).to.have.property('buyer')                 // passes

  // Is the mocked value still present?
  expect(revisedFixture.data.purchaseOrderId).to.eq('mock-this-value')  // passes
})

To do so automatically in the test, you will need to let the intercept query the server.

This is an approximate, obviously you will need to tweak for your app's data (JSON parse, etc)

cy.fixture(fixtureName).then(fixture => {
  cy.intercept(url, (req) => {
    req.continue().then(res => {
      const revisedFixture = Cypress._.merge(res, fixture) 
      res.send(revisedFixture)
    })
  })
})

Upvotes: 2

Related Questions