Skip to content

Commit

Permalink
fix(firestore-bigquery-export): update event types for Eventarc compa…
Browse files Browse the repository at this point in the history
…tibility (#1981)
  • Loading branch information
Gustolandia committed Dec 20, 2024
1 parent 5a9311b commit 925668e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 51 deletions.
71 changes: 24 additions & 47 deletions firestore-bigquery-export/functions/__tests__/functions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as admin from "firebase-admin";
import { logger } from "firebase-functions";
import * as functionsTestInit from "../node_modules/firebase-functions-test";
import mockedEnv from "../node_modules/mocked-env";
import { mockConsoleLog } from "./__mocks__/console";
import config from "../src/config";
import { mockConsoleLog } from "./__mocks__/console";

// Mock Firestore BigQuery Tracker
jest.mock("@firebaseextensions/firestore-bigquery-change-tracker", () => ({
Expand All @@ -19,11 +19,10 @@ jest.mock("@firebaseextensions/firestore-bigquery-change-tracker", () => ({
}));

// Mock firebase-admin eventarc
const channelMock = { publish: jest.fn() };
jest.mock("firebase-admin/eventarc", () => ({
getEventarc: jest.fn(() => ({
channel: jest.fn(() => ({
publish: jest.fn(),
})),
channel: jest.fn(() => channelMock),
})),
}));

Expand All @@ -36,6 +35,9 @@ jest.mock("../src/logs", () => ({
complete: jest.fn(() => logger.log("Completed execution of extension")),
}));

// Mock Console
console.info = jest.fn(); // Mock console.info globally

// Environment Variables
const defaultEnvironment = {
PROJECT_ID: "fake-project",
Expand All @@ -47,7 +49,7 @@ const defaultEnvironment = {
};

let restoreEnv;
let functionsTest = functionsTestInit();
let functionsTest;

/** Helper to Mock Export */
const mockExport = (document, data) => {
Expand All @@ -60,11 +62,12 @@ describe("extension", () => {
beforeEach(() => {
restoreEnv = mockedEnv(defaultEnvironment);
jest.resetModules();
functionsTest = functionsTestInit();
jest.clearAllMocks();
});

afterEach(() => {
restoreEnv();
jest.clearAllMocks();
});

test("functions are exported", () => {
Expand All @@ -79,9 +82,9 @@ describe("extension", () => {
functionsConfig = config;
});

test("function runs with a CREATE event and publishes both old and new events", async () => {
test("function runs with a CREATE event", async () => {
const beforeSnapshot = functionsTest.firestore.makeDocumentSnapshot(
{}, // Empty data to simulate no document
{}, // Empty to simulate no document
"example/doc1"
);
const afterSnapshot = functionsTest.firestore.makeDocumentSnapshot(
Expand All @@ -100,30 +103,17 @@ describe("extension", () => {

expect(callResult).toBeUndefined();

// Verify Logs
expect(mockConsoleLog).toBeCalledWith(
"Started execution of extension with configuration",
functionsConfig
);
expect(mockConsoleLog).toBeCalledWith("Completed execution of extension");

// Verify Event Publishing
const eventarcMock = require("firebase-admin/eventarc").getEventarc;
const channelMock = eventarcMock().channel();

expect(channelMock.publish).toHaveBeenCalledTimes(2);
expect(channelMock.publish).toHaveBeenCalledWith(
expect.objectContaining({
type: "firebase.extensions.firestore-counter.v1.onStart",
data: expect.any(Object),
})
);
expect(channelMock.publish).toHaveBeenCalledWith(
expect.objectContaining({
type: "firebase.extensions.firestore-bigquery-export.v1.onStart",
data: expect.any(Object),
backupBucketName: expect.any(String),
initialized: expect.any(Boolean),
maxDispatchesPerSecond: expect.any(Number),
maxEnqueueAttempts: expect.any(Number),
})
);

expect(mockConsoleLog).toBeCalledWith("Completed execution of extension");
});

test("function runs with a DELETE event", async () => {
Expand All @@ -132,7 +122,7 @@ describe("extension", () => {
"example/doc1"
);
const afterSnapshot = functionsTest.firestore.makeDocumentSnapshot(
{}, // Empty data to simulate no document
{}, // Empty to simulate document deletion
"example/doc1"
);

Expand All @@ -147,30 +137,17 @@ describe("extension", () => {

expect(callResult).toBeUndefined();

// Verify Logs
expect(mockConsoleLog).toBeCalledWith(
"Started execution of extension with configuration",
functionsConfig
);
expect(mockConsoleLog).toBeCalledWith("Completed execution of extension");

// Verify Event Publishing for both old and new event types
const eventarcMock = require("firebase-admin/eventarc").getEventarc;
const channelMock = eventarcMock().channel();

expect(channelMock.publish).toHaveBeenCalledTimes(2);
expect(channelMock.publish).toHaveBeenCalledWith(
expect.objectContaining({
type: "firebase.extensions.firestore-counter.v1.onCompletion",
data: expect.any(Object),
})
);
expect(channelMock.publish).toHaveBeenCalledWith(
expect.objectContaining({
type: "firebase.extensions.firestore-bigquery-export.v1.onCompletion",
data: expect.any(Object),
backupBucketName: expect.any(String),
initialized: expect.any(Boolean),
maxDispatchesPerSecond: expect.any(Number),
maxEnqueueAttempts: expect.any(Number),
})
);

expect(mockConsoleLog).toBeCalledWith("Completed execution of extension");
});
});
});
8 changes: 4 additions & 4 deletions firestore-bigquery-export/functions/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const setupEventChannel = () => {
* @returns A Promise resolving when both events are published.
*/
export const recordStartEvent = async (data: string | object) => {
if (!eventChannel) return;
if (!eventChannel) return Promise.resolve(); // Explicitly return a resolved Promise

const eventTypes = getEventTypes("onStart");

Expand All @@ -72,7 +72,7 @@ export const recordStartEvent = async (data: string | object) => {
* @returns A Promise resolving when both events are published.
*/
export const recordErrorEvent = async (err: Error, subject?: string) => {
if (!eventChannel) return;
if (!eventChannel) return Promise.resolve(); // Ensure consistent return type

const eventTypes = getEventTypes("onError");

Expand Down Expand Up @@ -103,7 +103,7 @@ export const recordSuccessEvent = async ({
subject: string;
data: string | object;
}) => {
if (!eventChannel) return;
if (!eventChannel) return Promise.resolve(); // Explicitly return a resolved Promise

const eventTypes = getEventTypes("onSuccess");

Expand All @@ -126,7 +126,7 @@ export const recordSuccessEvent = async ({
* @returns A Promise resolving when both events are published.
*/
export const recordCompletionEvent = async (data: string | object) => {
if (!eventChannel) return;
if (!eventChannel) return Promise.resolve(); // Ensure consistent return type

const eventTypes = getEventTypes("onCompletion");

Expand Down

0 comments on commit 925668e

Please sign in to comment.