1

I'm trying to stub a midi file in a Cypress intercept. From the URL I am deriving a fixture to load and use in the reply. I am doing something like:

cy.intercept("**/MIDI/*", (req) => {
  const fixtureName = get_last_part_of(req.url)  // This will yield a fixture like 1.mid
  req.reply( {
    headers: {
      'content-type': "audio/sp-midi"
    },
    fixture: "midi/" + fixtureName
  })

When I load this file I get an error in the browser logs about an invalid MIDI file:

ERROR Error: Uncaught (in promise): Bad MIDI file.  Expected 'MTrk', got: 'MTr'
    at resolvePromise (polyfills.js:8576:21)
    at polyfills.js:8485:11

I think this is because the 1.mid is treated as utf-8, but I want it to be treated as binary. Is there a way to specify this in the reply?

I've tried reading the file directly in the intercept but because I am using cy.visit that invokes the intercept, I am getting an error.

2 Answers2

2

There are some clues here Fixture - Default Encoding. The "known extensions" list doesn't include mid, and the following paragraph confirms that the default would be utf8.

From here Intercept - StaticResponse objects

Serve a fixture as the HTTP response body (allowed when body is omitted). Read the contents with an encoding other than the default for the file type, pass the fixture like path,encoding.

This might work:

cy.intercept("**/MIDI/*", (req) => {
  const fixtureName = get_last_part_of(req.url)  // This will yield a fixture like 1.mid
  req.reply( {
    headers: {
      'content-type': "audio/sp-midi"
    },
    fixture:  `midi/${fixtureName},binary`
  })

Using a sample midi

Here's a passing test using a very simple test page, following the information given in the question.

Sample page

<script>
  fetch('https://some-domain/api/MIDI/1.mid')
</script>

Test

cy.intercept('**/MIDI/*', (req) => {
  const fixtureName = req.url.split('/').pop()
  req.reply( {
    headers: {
      'content-type': "audio/sp-midi"
    },
    fixture:  `midi/${fixtureName},binary`
  })
}).as('midi')

cy.visit('midi.html')

cy.wait('@midi')

No error occurs, which makes me think you are looking in the wrong place.

user16695029
  • 3,365
  • 5
  • 21
  • Thanks for the quick answer. Unfortunately that didn't fix the problem. I should have added the error message that I am getting is: ``` ERROR Error: Uncaught (in promise): Bad MIDI file. Expected 'MTrk', got: 'MTr' at resolvePromise (polyfills.js:8576:21) ``` – Bradley Schmerl Apr 06 '23 at 21:19
  • The error actually comes from `tone.js` where it is trying to parse the MIDI. The reason I think it is an encoding error is because the file plays fine in a MIDI player, and the error doesn't occur if I remove the interceptor and get it from the link. I'll try to isolate a simple example that show's the problem. – Bradley Schmerl Apr 07 '23 at 13:25
0

I now have an answer to this, though I don't completely understand what is happening. Instead of using the binary encoding, I have to use null. So, if I do

cy.intercept('**/MIDI/*', (req) => {
  const fixtureName = req.url.split('/').pop()
  req.reply( {
    headers: {
      'content-type': "audio/sp-midi"
    },
    fixture:  `midi/${fixtureName},null`
  })
})

I no longer get the MIDI error.

The way that I discovered this was to copy the resource as an asset in the app I was testing, and have the intercept request the MIDI file from there. I noticed that the length of the body was 191. Then, I compared the response loaded from the intercepted fixture, and noticed that it was 220. The same thing was happening when I checked the length using the result of cy.readFile(<fixturefile>, 'binary'), until I set null encoding. This creates a buffer that is used in the body of the message, rather than a "binary" representation of it.