Itsu
Itsu

Reputation: 31

Why an error "connect ECONNREFUSED 127.0.0.1:8080" occurs when testing firestore rules with npm

I wanted to test a firestore rule. Below is firestore.rules. I wanted to check that these security rules are valid. Then I tried to use jest and firebase testing. However when executing "npm test", an error, "connect ECONNREFUSED 127.0.0.1:8080" occured.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /clubUsers/{uid} {
      allow read: if request.auth != null
        && request.auth.uid == uid;
      allow create: if request.auth != null
        && request.auth.uid == uid;   
      allow update: if request.auth != null
        && request.auth.uid == uid;  
    }
  }
}

And my test script is here.

const firebase = require('@firebase/testing/');
const fs = require('fs');

const project_id = "PROJECT ID";

describe("testing firestore rules", () => {

    beforeAll(
        async () => {
            await firebase.loadFirestoreRules({
                projectId: project_id,
                rules: fs.readFileSync('../../firestore.rules', 'utf8'),
            });
        }
    );

    afterEach(
        async () => {
            await firebase.clearFirestoreData({ projectId: project_id });
        }
    );

    afterAll(
        async () => {
            await Promise.all(
                firebase.apps().map((app) => app.delete())
            );
        }
    );

    function authedApp(auth) {
        return firebase.initializeTestApp({
            projectId: project_id,
            auth: auth,
        }).firestore();
    }

    describe("testing get and write", () => {

        test("testing get", async () => {
            const db = authedApp({ uid: 'UID' });
            const message = db.collection("clubUsers").doc("UID");
            await firebase.assertSucceeds(message.get());
        })

        test("testing write", async () => {
            const db = authedApp({ uid: "UID" });
            const message = db.collection("clubUsers").doc("UID");
            await firebase.assertSucceeds(
                message.set({ text: "hoge" })
            );
        })
    })

})

I tried the test while firebase emulator is opened.

I checked what is using port 8080 by executing sudo lsof -P -i:8080 on terminal. However, nothing has used port 8080.

Upvotes: 3

Views: 1149

Answers (2)

earendil06
earendil06

Reputation: 15

I encountered the same issue after upgrading the version of node from 16 to 18.

Node 18 prefers IPv6 over IPv4. And inside the latest version of firebase-functions-test module (3.1.1), the function clearFirestoreData contains hardcoded host value: localhost, and ignores what you specify with FIRESTORE_EMULATOR_HOST env variable. With node 18, localhost is resolved by an IPv6.

I solved it by adding an extra node option before running jest.

NODE_OPTIONS='--dns-result-order=ipv4first'

With this, I could keep the clearFirestoreData inside my beforeEach hook.

Upvotes: 0

jt_uk
jt_uk

Reputation: 1532

Just ran into this too today... a couple of sources (GitHub and here) led to a solution. This is an issue with the call to firebase.clearFirestoreData() and occurs when the emulator can't be found on the default host:port it is expecting.

The solutions suggest setting an environment variable to define the host and port that works for your setup. For example:

process.env.FIRESTORE_EMULATOR_HOST = '127.0.0.1:5002';

You can find the correct host:port combination to use after you've fired up the emulators with firebase emulators:start

This has been addressed in the new modular v9 JS SDK, but does require a bit of refactoring to the new API (as defined in the docs). You can now specify the host and port when initialising:

testEnv = await initializeTestEnvironment({
    projectId: projectId,
    firestore: {
        host: '127.0.0.1',
        port: 5002,
    }
});

PS. Don't also be fooled like I was by assuming that 127.0.0.1 and localhost are always the same!

Upvotes: 4

Related Questions