javascript - Firebase storage unit tests: Timeout when trying to upload files using emulator - Stack Overflow

When running the below test via npm test, I get the following output:Error: Timeout of 2000ms exceeded

When running the below test via npm test, I get the following output:

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/Users/[myname]/development/Construct/construct/infra/test/storage.test.js)
      at listOnTimeout (node:internal/timers:564:17)
      at process.processTimers (node:internal/timers:507:7)

I have the storage emulator running, with output telling me it is running on 127.0.0.1:9199

You'll notice I have a debug statement in storage.rules. This is consistently outputting a result, so the rules do appear to be getting run.

I can't find definitive documentation on what env var I should be setting, but it seems like process.env.STORAGE_EMULATOR_HOST is probably the right one?

My colleague, running the same test on his machine, is finding it runs successfully. So it seems the problem is somehow connected to my local setup.

I also have tests that test firestore.rules as well as storage.rules (running against the Firestore emulator) and they run with no problem.

Edit: I fot to mention, the file is being successfully uploaded to storage. It just seems to be the promise that's timing out.

My environment

node -v: v18.0.0 npm -v: 8.6.0 firebase --version: 13.32.0 macOS 15.3.1 (24D70)

Related links

I came across this while searching for a solution: I appear to have the same problem.

Steps to reproduce

Run the storage emulator, check the host and port match what's being set in STORAGE_EMULATOR_HOST in storage.test.js, then run the test in storage.test.js via npm test.

Expected behavior

I expect to get feedback on whether my test has passed or failed, as I do for my firestore.rules tests, eg "PERMISSION_DENIED" when I expect permission to be denied, and a green tick when tests pass.

My code

storage.test.js:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
} from "@firebase/rules-unit-testing";
import { ref, uploadBytes } from "firebase/storage";
import { readFileSync } from "fs";
import { afterEach, describe, it } from "mocha";
import { v4 as uuid_v4 } from "uuid";

process.env.STORAGE_EMULATOR_HOST = "127.0.0.1:9199";
//process.env.DATASTORE_EMULATOR_HOST = "127.0.0.1:9199";
const projectId = "app-construct-firebase-storage-security-rules-test";
const firebaseStorage = {
  rules: readFileSync("./../storage.rules", "utf8"),
  host: "127.0.0.1",
  port: 9199,
};

const testEnv = await initializeTestEnvironment({
  projectId: projectId,
  storage: firebaseStorage,
});

describe("firebase storage security rules unit tests", () => {
  const userID = uuid_v4();
  const userEmail = "[email protected]";

  const tokenOptions = {
    email: userEmail,
  };

  function avatarPath(myUserID) {
    return `avatars/${myUserID}`;
  }

  describe("********** `avatars` storage **********", () => {
    it("users can only create avatars stored against their own user ID", async () => {
      const storage = testEnv
        .authenticatedContext(userID, tokenOptions)
        .storage();
      const image = readFileSync("./dummy-avatar.png");
      const storagePath = avatarPath(userID);

      const userImageRef = storage.ref(storagePath);
      await assertSucceeds(
        userImageRef.put(image, { contentType: "image/png" })
      );
    });
  });
});

storage.rules:

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read;
    }

    match /avatars/{userID} {
      allow write, delete: if debug(request.auth.uid) == debug(userID);
    }
  }
}

firebase.json:

{
  "hosting": {
    "public": "app/build/web",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "firestore": {
    "rules": "infra/firestore.rules"
  },
  "storage": {
    "rules": "infra/storage.rules"
  },
  "emulators": {
    "auth": {
      "port": 9099
    },
    "firestore": {
      "port": 8080
    },
    "storage": {
      "port": 9199
    },
    "ui": {
      "enabled": true
    },
    "singleProjectMode": false
  },
  "functions": [
    {
      "source": "functions",
      "codebase": "default",
      "ignore": ["venv", ".git", "firebase-debug.log", "firebase-debug.*.log"]
    }
  ]
}

package.json:

{
  "name": "security-rules-tests",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "mocha \"./storage.test.js\" --exit"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@firebase/rules-unit-testing": "^3.0.4",
    "firebase-admin": "^12.7.0",
    "firebase-tools": "^13.20.2",
    "mocha": "^10.7.3",
    "uuid": "^11.0.3"
  }
}

Debug info

npm test --debug gives the same output.

But if I check firestore-debug.log, I see this:

Mar 03, 2025 8:52:05 PM io.gapi.emulatorsty.HttpVersionRoutingHandler channelRead INFO: Detected non-HTTP/2 connection.

...and if I check firebase-debug.log, I see this:

[debug] [2025-03-03T20:55:36.909Z] >>> [apiv2][query] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast [none] [debug] [2025-03-03T20:55:36.909Z] >>> [apiv2][body] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast {"specversion":"1.0","id":"25e21402-0f42-4bf9-9197-7414f86c2eae","type":"google.cloud.storage.object.v1.finalized","source":"//storage.googleapis/projects/_/buckets/app-construct-firebase-storage-security-rules-test/objects/avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8","time":"2025-03-03T20:55:36.888Z","data":{"kind":"storage#object","name":"avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8","bucket":"app-construct-firebase-storage-security-rules-test","generation":"1741035336888","metageneration":"1","contentType":"image/png","timeCreated":"2025-03-03T20:55:36.888Z","updated":"2025-03-03T20:55:36.888Z","storageClass":"STANDARD","size":"561","md5Hash":"nWSYBL5eqqiZUZaMdncOqg==","etag":"3ZOhitoec/6YbVv42oz62nkv+BY","metadata":{"firebaseStorageDownloadTokens":"f5e7cfc7-8d49-43c5-b642-5345153f2748"},"crc32c":"16/Irg==","timeStorageClassUpdated":"2025-03-03T20:55:36.888Z","id":"app-construct-firebase-storage-security-rules-test/avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8/1741035336888","selfLink":"http://127.0.0.1:9199/storage/v1/b/app-construct-firebase-storage-security-rules-test/o/avatars%2F37d5ca50-211d-4d0c-993c-771c5668e0f8","mediaLink":"http://127.0.0.1:9199/download/storage/v1/b/app-construct-firebase-storage-security-rules-test/o/avatars%2F37d5ca50-211d-4d0c-993c-771c5668e0f8?generation=1741035336888&alt=media"}} [debug] [2025-03-03T20:55:36.914Z] <<< [apiv2][status] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast 200 [debug] [2025-03-03T20:55:36.914Z] <<< [apiv2][body] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast {"status":"multicast_acknowledged"}

...and if I check database-debug.log, I see nothing recent.

(I'm not actually sure which of these files is the one relevant to storage rules?)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745071506a4609575.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信