From 0862b157d8cc0532c072f00fa5e7e2fea22f0143 Mon Sep 17 00:00:00 2001 From: kyungseopk1m Date: Wed, 29 Jul 2026 11:25:12 +0900 Subject: [PATCH 1/2] fix(eventarc): resolve the emulator host when the client is constructed --- src/eventarc/eventarc-client-internal.ts | 8 +-- test/unit/eventarc/eventarc.spec.ts | 73 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/eventarc/eventarc-client-internal.ts b/src/eventarc/eventarc-client-internal.ts index a9fc162f7a..09ad5f9cf9 100644 --- a/src/eventarc/eventarc-client-internal.ts +++ b/src/eventarc/eventarc-client-internal.ts @@ -42,6 +42,7 @@ const DEFAULT_CHANNEL_REGION = 'us-central1'; */ export class EventarcApiClient { private readonly httpClient: HttpClient; + private readonly eventarcHost: string; private projectId?: string; private readonly resolvedChannelName: Promise; @@ -53,6 +54,7 @@ export class EventarcApiClient { }); } this.httpClient = new AuthorizedHttpClient(app as FirebaseApp); + this.eventarcHost = process.env.CLOUD_EVENTARC_EMULATOR_HOST ?? EVENTARC_API; this.resolvedChannelName = this.resolveChannelName(channel.name); } @@ -105,7 +107,7 @@ export class EventarcApiClient { } const request: HttpRequestConfig = { method: 'POST', - url: `${this.getEventarcHost()}/${channel}:publishEvents`, + url: `${this.eventarcHost}/${channel}:publishEvents`, data: JSON.stringify({ events }), }; return this.sendRequest(request); @@ -162,8 +164,4 @@ export class EventarcApiClient { const projectId = await this.getProjectId(); return `projects/${projectId}/locations/${location}/channels/${channelId}`; } - - private getEventarcHost(): string { - return process.env.CLOUD_EVENTARC_EMULATOR_HOST ?? EVENTARC_API; - } } diff --git a/test/unit/eventarc/eventarc.spec.ts b/test/unit/eventarc/eventarc.spec.ts index 55cc853b4a..594189434c 100644 --- a/test/unit/eventarc/eventarc.spec.ts +++ b/test/unit/eventarc/eventarc.spec.ts @@ -59,6 +59,8 @@ const TEST_EVENT2 : CloudEvent = { }; const TEST_EVENT2_SERIALIZED = JSON.stringify(toCloudEventProtoFormat(TEST_EVENT2)); +const EMULATOR_HOST = 'http://127.0.0.1:9299'; + describe('eventarc', () => { let mockApp: FirebaseApp; let eventarc: Eventarc; @@ -168,6 +170,77 @@ describe('eventarc', () => { }); }); + describe('emulator host', () => { + let mockAccessToken: string; + let httpStub: sinon.SinonStub; + let accessTokenStub: sinon.SinonStub; + + before(() => { + mockAccessToken = utils.generateRandomAccessToken(); + accessTokenStub = utils.stubGetAccessToken(mockAccessToken); + }); + + after(() => { + accessTokenStub?.restore(); + }); + + afterEach(() => { + httpStub?.restore(); + delete process.env.CLOUD_EVENTARC_EMULATOR_HOST; + }); + + it('is resolved at construction time', async () => { + delete process.env.CLOUD_EVENTARC_EMULATOR_HOST; + const prodChannel = eventarc.channel(); + + process.env.CLOUD_EVENTARC_EMULATOR_HOST = EMULATOR_HOST; + const emulatorChannel = eventarc.channel(); + + delete process.env.CLOUD_EVENTARC_EMULATOR_HOST; + + httpStub = sinon + .stub(HttpClient.prototype, 'send') + .resolves(utils.responseFrom({})); + + await prodChannel.publish(TEST_EVENT1); + await emulatorChannel.publish(TEST_EVENT1); + + expect(httpStub).to.have.been.calledTwice; + expect(httpStub.firstCall).to.have.been.calledWith({ + method: 'POST', + url: 'https://eventarcpublishing.googleapis.com/v1/projects/project_id/locations/us-central1/channels/firebase:publishEvents', + data: `{"events":[${TEST_EVENT1_SERIALIZED}]}`, + headers: getExpectedHeaders(mockAccessToken) + }); + expect(httpStub.secondCall).to.have.been.calledWith({ + method: 'POST', + url: `${EMULATOR_HOST}/projects/project_id/locations/us-central1/channels/firebase:publishEvents`, + data: `{"events":[${TEST_EVENT1_SERIALIZED}]}`, + headers: getExpectedHeaders(mockAccessToken) + }); + }); + + it('is not picked up by a channel created before it was set', async () => { + delete process.env.CLOUD_EVENTARC_EMULATOR_HOST; + const prodChannel = eventarc.channel(); + + process.env.CLOUD_EVENTARC_EMULATOR_HOST = EMULATOR_HOST; + + httpStub = sinon + .stub(HttpClient.prototype, 'send') + .resolves(utils.responseFrom({})); + + await prodChannel.publish(TEST_EVENT1); + + expect(httpStub).to.have.been.calledOnce.and.calledWith({ + method: 'POST', + url: 'https://eventarcpublishing.googleapis.com/v1/projects/project_id/locations/us-central1/channels/firebase:publishEvents', + data: `{"events":[${TEST_EVENT1_SERIALIZED}]}`, + headers: getExpectedHeaders(mockAccessToken) + }); + }); + }); + describe('full resource name Channel', () => { let channel : Channel; let mockAccessToken: string; From 5e5a1dbfd0a107abc81583bf0cc6dec1e1376e6e Mon Sep 17 00:00:00 2001 From: kyungseopk1m Date: Wed, 29 Jul 2026 11:43:20 +0900 Subject: [PATCH 2/2] test(eventarc): restore the emulator host env var after the suite --- test/unit/eventarc/eventarc.spec.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/eventarc/eventarc.spec.ts b/test/unit/eventarc/eventarc.spec.ts index 594189434c..2ecc4299c8 100644 --- a/test/unit/eventarc/eventarc.spec.ts +++ b/test/unit/eventarc/eventarc.spec.ts @@ -174,14 +174,21 @@ describe('eventarc', () => { let mockAccessToken: string; let httpStub: sinon.SinonStub; let accessTokenStub: sinon.SinonStub; + let originalEmulatorHost: string | undefined; before(() => { mockAccessToken = utils.generateRandomAccessToken(); accessTokenStub = utils.stubGetAccessToken(mockAccessToken); + originalEmulatorHost = process.env.CLOUD_EVENTARC_EMULATOR_HOST; }); after(() => { accessTokenStub?.restore(); + if (originalEmulatorHost === undefined) { + delete process.env.CLOUD_EVENTARC_EMULATOR_HOST; + } else { + process.env.CLOUD_EVENTARC_EMULATOR_HOST = originalEmulatorHost; + } }); afterEach(() => {