GoogleCloudPlatform / functions-framework-nodejs

FaaS (Function as a service) framework for writing portable Node.js functions
Apache License 2.0
1.29k stars 158 forks source link

Export Server #463

Closed penx closed 2 years ago

penx commented 2 years ago

Add export * from server to index.ts.

Use case

I would like to use @google-cloud/functions-framework for integration tests of a Remix Firebase functions adapter, to start and stop a functions server during Playwright tests.

The existing integration tests for Remix use their Express adapter:

      let port = await getPort();
      let app = express();
      app.use(express.static(path.join(fixture.projectDir, "public")));
      app.all(
        "*",
        createExpressHandler({ build: fixture.build, mode: "production" })
      );

      let server = app.listen(port);

https://github.com/remix-run/remix/blob/6a2bf52d9ca60e2ce6459ebe72df28e6a568ed26/integration/helpers/create-fixture.ts#L97-L121

I would like to run the same tests against a Firebase adapter I am working on.

The difference between the Express adapter and Firebase adapter is primarily the use of rawBody, and I'd like to ensure the integration tests still succeed given this difference. I need a functions server to use in the integration tests that behaves as per production deployments of Firebase functions.

I can update the above code to the following:

      let port = await getPort();
      let functionsPort = await getPort();
      let app = express();
      app.use(express.static(path.join(fixture.projectDir, "public")));
      app.all("*", proxy(`localhost:${functionsPort}`));
      let server = app.listen(port);
      let functionsServer = functions.getServer(
        createFirebaseHandler({
          build: fixture.build,
          mode: "production",
        }),
        "http"
      );
      functionsServer.listen(functionsPort);

...but this requires access to the getServer function.

I looked at other libraries such as the emulators in firebase-tools, but these require the functions to exist as files on disk. In the tests above, the functions need to be created per test using fixture.build as an argument.

The getTestServer exported from testing.ts has 2 issues preventing me from using it for this purpose:

penx commented 2 years ago

Since opening this, I've realised that I can use getTestServer as follows:

import { http } from "@google-cloud/functions-framework";
import { getTestServer } from "@google-cloud/functions-framework/testing";

http(
  "remixServer",
  createFirebaseHandler({
    build: fixture.build,
    mode: "production",
  })
);
let functionsServer = getTestServer("remixServer");

However:

ChrisChiasson commented 1 year ago

For those still getting Cannot find module '@google-cloud/functions-framework/testing' or its corresponding type declarations.ts(2307) in modern times, the fix is here as dimip1606 calls out. I note that "moduleResolution": "nodenext" needs to go under compilerOptions, not at the top level.