Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Writing unit tests with jsdom in third party apps errors out for storage #6441

Closed
Yuangwang opened this issue Jul 15, 2022 · 1 comment
Closed

Comments

@Yuangwang
Copy link

Yuangwang commented Jul 15, 2022

[REQUIRED] Describe your environment

  • Operating System version: macOS Monterey 12.4
  • Browser version: 103.0.5060.114
  • Firebase SDK version: storage/0.9.9
  • Firebase Product: storage (auth, database, storage, etc)

[REQUIRED] Describe the problem

Third party Jsdom unit tests are failing with an unknown error whenever uploadString/bytes is called from the firebase storage sdks. The issue is ultimately caused by jsdom using its own implementation of Blob which doesn't work well with the node-fetch library that we're using.

The JSDOM Blob implementation doesn't have arrayBuffer implemented and they don't seem to have any intention of implementing it in the future. (See this thread for more context jsdom/jsdom#2555) Node fetch relies on arrayBuffer to be implemented to check if an object is a Blob and seems to rely on arrayBuffer to parse the blob.(https://github.com/node-fetch/node-fetch/blob/main/src/utils/is.js#L34)

Because of these issues the string "[object Blob]" is being sent over toe the storage backend instead of the actual contents of the Blob.

UPDATE

Taking another step back, the issue seems to be that JSDOM and node modules are interacting in the first place. JSDOM is normally used to simulate browser methods in unit tests so it doesn't really make sense to use node-fetch in the first place, we should be using XHR instead.

The fix would be to make changes in the webpack config so jsdom tests point to the browser bundle instead of the node bundle.

Steps to reproduce:

This repo was created with Create-React-App and contains a unit test that breaks due to this issue https://github.com/tjlav5/storage-emulator

Create react app seems to point to the node bundle by default when running jsdom unit tests so that is what causes the issue, changing this to point to the browser bundle for jsdom tests should fix this.

@hsubox76
Copy link
Contributor

We are not currently going to prioritize fixing this, as JSDOM, if I understand correctly, is used in cases where you want to test a web app built to run in a browser environment. In this case, the actual web app would use the Firebase Storage browser bundle, and any unit tests should probably be using that same Firebase Storage bundle. node-fetch, which is mishandling JSDOM's Blob format here, is only used in the Firebase Storage Node bundle.

Unfortunately it seems that some test runners are configured by default to resolve to Node bundles (prefer "main" over "browser" or "module") when running tests in JSDOM (Jest seems to do this?) and so it's pulling in a different Firebase Storage bundle (the Node version) during the test run than it does in the actual app (where it would get the browser bundle).

It seems like the best solution for users having this issue in their tests is to configure the module resolution in their test build config (webpack config, or use jest.mock to point to a specified Firebase bundle) to point to the Firebase Storage browser bundle, either by preferring "browser" or "module" fields over "main", if that's possible, or by using some kind of alias functionality to force any references to @firebase/storage to always import @firebase/storage/dist/index.browser.esm2017.js, for example, specifically.

I think this is better for the user as well, as you don't want your tests to be importing a completely different Firebase file than your app, since you want your test conditions to match production conditions as well as you can.

I know module resolution configuration can be difficult in a lot of frameworks, such as Create React App, where last I checked, you couldn't change the module resolution order in the webpack config without ejecting, but if anyone has any tips for how to easily do so, feel free to drop them here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants