3

I am doing some Integration tests with jest & nock to test Axios interceptors chaining.
In one of them, I am expecting to receive a Blob instance
and according to this link, I should be able to use its text() method.
My question is: Why is this method not defined? (in my tests)

Here is the (simplified) code:

// interceptors.js
const useBlobTextProperty = async (response) => {
  const { data: myBlob } = response
  console.log(myBlob.toString())          // Prints "[object Blob]"
  response.rawText = await myBlob.text()  // TypeError: myBlob.text is not a function
  return response
}
// foo.test.js
import axios from 'axios'
import httpAdapter from 'axios/lib/adapters/http'
import nock from 'nock'

const testAxios = axios.create({
  responseEncoding: 'utf8',
  responseType: 'blob',
})
testAxios.interceptors.response.use(useBlobTextProperty, null)

const host = 'http://localhost'

axios.defaults.host = host
axios.defaults.adapter = httpAdapter

describe('SO test', () => {
  beforeEach(() => {
    nock(host)
      .defaultReplyHeaders({ 'Content-Type': 'application/json' })
      .persist()
      .get('/')
      .reply(200, { foo: 17 })
  })
  afterEach(() => {
    nock.cleanAll()
  })

  it('should get raw text', async () => {
    const returnValue = await testAxios.get('/') // FAIL: TypeError
    expect(returnValue.rawText).toEqual('{"foo":17}')
  }, 1000)
})

FYI, to workaround this issue, I am using another interceptor:

// interceptors.js
const addMissingTextPropertyToBlob = (response) => {
  const { data } = response
  if (data.toString() === '[object Blob]' && !data.text) {
    data.text = () =>
      new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = () => { resolve(reader.result) }
        reader.onerror = (error) => { reject(error) }
        reader.readAsText(data)
      })
  }
  return response
}
// foo.test.js
// Response interceptors are executed from index 0 to N-1
testAxios.interceptors.response.use(addMissingTextPropertyToBlob, null)
testAxios.interceptors.response.use(useBlobTextProperty, null)
// Then, it works!

But I'd like to understand why I cannot rely on Blob.text() in my tests.

fservantdev
  • 528
  • 8
  • 18
  • Where are you running this code? The [`text` method of `Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/text) is not universally supported. – Bergi Dec 16 '20 at 17:37
  • I am running this code on my local machine, through VS Code. When I run my code in real, it works well (i.e.: without `addMissingTextPropertyToBlob`) on both Chrome, Edge & Firefox. – fservantdev Dec 16 '20 at 17:50
  • VS Code doesn't run code by itself. Where does VS Code run the code? – Bergi Dec 16 '20 at 17:52
  • Sorry: to launch my tests, I execute `yarn test` (i.e.: `npx jest`) in the VS Code's terminal of my machine (Windows 10 Pro) – fservantdev Dec 16 '20 at 17:57
  • And what does the `test` script in your package.json do? – Bergi Dec 16 '20 at 17:58
  • It does `"test": "jest"` – fservantdev Dec 16 '20 at 17:58
  • And jest will run the `foo.test.js` in a node.js environment, not in a browser?! – Bergi Dec 16 '20 at 18:00
  • Euh yes ^^, should I conclude that it behaves as expected? I am using nock for HTTP server mocking. Shouldn't axios or nock provide the proper blob API when I receive the response? – fservantdev Dec 16 '20 at 18:02
  • 1
    If you're using Nock, I assume you're running this in Node. keep in mind that Node doesn't have native support for Blob. So Axios is doing something funky to mimic a Blob when `responseType: 'blob'` is provided. – Matt R. Wilson Dec 16 '20 at 18:05
  • OK, so using an interceptor like `addMissingTextPropertyToBlob` is the right way to correctly set up my tests. Thanks. I let you write the proper answer, otherwise I can/will do it myself! – fservantdev Dec 16 '20 at 18:12
  • 1
    …or you just open a feature request with that nock library to implement the full API. Which, as you demonstrated, isn't hard. – Bergi Dec 16 '20 at 21:12

1 Answers1

5

In my case, this approach worked for me:

yarn add blob-polyfill -D

and then import the following in your jest setupTests:

import 'blob-polyfill';

Washington Braga
  • 1,593
  • 15
  • 14