Skip to content

Commit

Permalink
Fix bug where callable functions can't be emulated. (#4314)
Browse files Browse the repository at this point in the history
Fixes #4313

In #4310, we started to support new type of triggers `callableTrigger` (distinct from `httpTrigger`).

Functions Emulator does not support `callableTrigger`. We fix this by converting `callbleTrigger` to `httpTrigger`. This is tech debt - at some point, we should use `endpoint` definitions throughout the emulator (cc @joehan).

Also adds integration tests for emulating callable triggers to prevent this kind of breakages in the future.
  • Loading branch information
taeold committed Mar 17, 2022
1 parent a41686f commit 206041a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- Adds support for configuration with multiple storage targets (#4281).
- Fixes bug where callable functions couldn't be emulated (#4314).
15 changes: 15 additions & 0 deletions scripts/integration-helpers/framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,21 @@ export class TriggerEndToEndTest {
return fetch(url);
}

invokeCallableFunction(
name: string,
body: Record<string, unknown>,
zone = FIREBASE_PROJECT_ZONE
): Promise<Response> {
const url = `http://localhost:${this.functionsEmulatorPort}/${[this.project, zone, name].join(
"/"
)}`;
return fetch(url, {
method: "POST",
body: JSON.stringify(body),
headers: { "Content-Type": "application/json" },
});
}

writeToRtdb(): Promise<Response> {
return this.invokeHttpFunction("writeToRtdb");
}
Expand Down
10 changes: 10 additions & 0 deletions scripts/triggers-end-to-end-tests/functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ exports.storageMetadataReaction = functions.storage
return true;
});

exports.onCall = functions.https.onCall((data) => {
console.log("data", JSON.stringify(data));
return data;
});

exports.storagev2archivedreaction = functionsV2.storage.onObjectArchived((cloudevent) => {
console.log(STORAGE_FUNCTION_V2_ARCHIVED_LOG);
console.log("Object", JSON.stringify(cloudevent.data));
Expand Down Expand Up @@ -359,3 +364,8 @@ exports.storagebucketv2metadatareaction = functionsV2.storage.onObjectMetadataUp
return true;
}
);

exports.oncallv2 = functionsV2.https.onCall((req) => {
console.log("data", JSON.stringify(req.data));
return req.data;
});
37 changes: 37 additions & 0 deletions scripts/triggers-end-to-end-tests/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,43 @@ describe("storage emulator function triggers", () => {
});
});

describe("onCall function triggers", () => {
let test: TriggerEndToEndTest;

before(async function (this) {
this.timeout(TEST_SETUP_TIMEOUT);

expect(FIREBASE_PROJECT).to.exist.and.not.be.empty;

const config = readConfig();
test = new TriggerEndToEndTest(FIREBASE_PROJECT, __dirname, config);
await test.startEmulators(["--only", "functions"]);
});

after(async function (this) {
this.timeout(EMULATORS_SHUTDOWN_DELAY_MS);
await test.stopEmulators();
});

it("should make a call to v1 callable function", async function (this) {
this.timeout(EMULATOR_TEST_TIMEOUT);

const response = await test.invokeCallableFunction("onCall", { data: "foobar" });
expect(response.status).to.equal(200);
const body = await response.json();
expect(body).to.deep.equal({ result: "foobar" });
});

it("should make a call to v2 callable function", async function (this) {
this.timeout(EMULATOR_TEST_TIMEOUT);

const response = await test.invokeCallableFunction("oncallv2", { data: "foobar" });
expect(response.status).to.equal(200);
const body = await response.json();
expect(body).to.deep.equal({ result: "foobar" });
});
});

describe("import/export end to end", () => {
it("should be able to import/export firestore data", async function (this) {
this.timeout(2 * TEST_SETUP_TIMEOUT);
Expand Down
3 changes: 3 additions & 0 deletions src/emulator/functionsEmulatorShared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ export function emulatedFunctionsFromEndpoints(
// process requires it in this form. Need to work in Firestore emulator for a proper fix...
if (backend.isHttpsTriggered(endpoint)) {
def.httpsTrigger = endpoint.httpsTrigger;
} else if (backend.isCallableTriggered(endpoint)) {
def.httpsTrigger = {};
def.labels = { ...def.labels, "deployment-callable": "true" };
} else if (backend.isEventTriggered(endpoint)) {
const eventTrigger = endpoint.eventTrigger;
if (endpoint.platform === "gcfv1") {
Expand Down

0 comments on commit 206041a

Please sign in to comment.